agent-device 0.21.4 → 0.21.6
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/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.4.apk → agent-device-android-ime-helper-0.21.6.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.6.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.21.4.manifest.json → agent-device-android-ime-helper-0.21.6.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.4.apk → agent-device-android-snapshot-helper-0.21.6.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.6.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.21.4.manifest.json → agent-device-android-snapshot-helper-0.21.6.manifest.json} +6 -6
- package/apple/snapshot-bridge/SnapshotBridgeRuntime.m +8 -1
- package/dist/src/adapter.js +1 -1
- package/dist/src/adb-executor.js +2 -2
- package/dist/src/adb-transport.js +1 -0
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/android-adb.js +1 -1
- package/dist/src/android.js +1 -1
- package/dist/src/app-helpers.js +1 -1
- package/dist/src/app-lifecycle.js +3 -3
- package/dist/src/app-log-reconnect.js +1 -1
- package/dist/src/app-log-runtime2.js +1 -1
- package/dist/src/device-input-state.d.ts +3 -4
- package/dist/src/device-session.js +1 -1
- package/dist/src/file.js +1 -1
- package/dist/src/internal/bin.js +1 -1
- package/dist/src/internal/run-script-http-child.d.ts +1 -1
- package/dist/src/ios-snapshot-runtime.js +1 -1
- package/dist/src/limrun-runtime-dependencies.js +1 -1
- package/dist/src/logcat.js +1 -1
- package/dist/src/mechanics.js +16 -16
- package/dist/src/perf-runtime-plan.js +1 -1
- package/dist/src/platform-runtime-android-adb-host.js +1 -1
- package/dist/src/runner-cache-metadata.js +2 -2
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runtime4.js +4 -4
- package/dist/src/semantic-index.js +1 -1
- package/dist/src/session2.js +5 -5
- package/dist/src/snapshot-process.js +1 -1
- package/dist/src/tree.js +1 -1
- package/dist/src/video.js +2 -2
- package/package.json +2 -2
- package/server.json +2 -2
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.21.4.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.21.4.apk.sha256 +0 -1
- package/dist/src/adb-host.js +0 -1
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
c705e3732af1307e0bf9f9ec058c898839ff695ffa9f3b9fcffe08ba63458487 agent-device-android-ime-helper-0.21.6.apk
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "android-ime-helper",
|
|
3
|
-
"version": "0.21.
|
|
4
|
-
"assetName": "agent-device-android-ime-helper-0.21.
|
|
5
|
-
"sha256": "
|
|
3
|
+
"version": "0.21.6",
|
|
4
|
+
"assetName": "agent-device-android-ime-helper-0.21.6.apk",
|
|
5
|
+
"sha256": "c705e3732af1307e0bf9f9ec058c898839ff695ffa9f3b9fcffe08ba63458487",
|
|
6
6
|
"packageName": "com.callstack.agentdevice.imehelper",
|
|
7
|
-
"versionCode":
|
|
7
|
+
"versionCode": 21006,
|
|
8
8
|
"serviceComponent": "com.callstack.agentdevice.imehelper/.TestInputMethodService",
|
|
9
9
|
"broadcastProtocol": "android-ime-helper-v1"
|
|
10
10
|
}
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
a4c52106edd24230c2d7a89e955bd43be8115d39b5d0994f674cb4e93fe049e6 agent-device-android-snapshot-helper-0.21.6.apk
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "android-snapshot-helper",
|
|
3
|
-
"version": "0.21.
|
|
4
|
-
"releaseTag": "v0.21.
|
|
5
|
-
"assetName": "agent-device-android-snapshot-helper-0.21.
|
|
3
|
+
"version": "0.21.6",
|
|
4
|
+
"releaseTag": "v0.21.6",
|
|
5
|
+
"assetName": "agent-device-android-snapshot-helper-0.21.6.apk",
|
|
6
6
|
"apkUrl": null,
|
|
7
|
-
"sha256": "
|
|
8
|
-
"checksumName": "agent-device-android-snapshot-helper-0.21.
|
|
7
|
+
"sha256": "a4c52106edd24230c2d7a89e955bd43be8115d39b5d0994f674cb4e93fe049e6",
|
|
8
|
+
"checksumName": "agent-device-android-snapshot-helper-0.21.6.apk.sha256",
|
|
9
9
|
"packageName": "com.callstack.agentdevice.snapshothelper",
|
|
10
|
-
"versionCode":
|
|
10
|
+
"versionCode": 21006,
|
|
11
11
|
"instrumentationRunner": "com.callstack.agentdevice.snapshothelper/.SnapshotInstrumentation",
|
|
12
12
|
"minSdk": 23,
|
|
13
13
|
"targetSdk": 36,
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
NSString *const kProtocolVersionKey = @"protocolVersion";
|
|
19
19
|
NSString *const kSourceVersionKey = @"sourceVersion";
|
|
20
20
|
NSString *const kRequestIdKey = @"requestId";
|
|
21
|
-
NSString *const kSourceVersion = @"agent-device-simulator-ax-v1.
|
|
21
|
+
NSString *const kSourceVersion = @"agent-device-simulator-ax-v1.6.0";
|
|
22
22
|
const NSUInteger kProtocolVersion = 1;
|
|
23
23
|
const uint32_t kMaximumFrameBytes = 16 * 1024 * 1024;
|
|
24
24
|
const NSUInteger kMaximumDepth = 128;
|
|
@@ -32,6 +32,7 @@ static NSString *const kAttributeValue = @"XC_kAXXCAttributeValue";
|
|
|
32
32
|
static NSString *const kAttributeIdentifier = @"XC_kAXXCAttributeIdentifier";
|
|
33
33
|
static NSString *const kAttributeFrame = @"XC_kAXXCAttributeFrame";
|
|
34
34
|
static NSString *const kAttributeAutomationType = @"XC_kAXXCAttributeAutomationType";
|
|
35
|
+
static NSString *const kAttributeTraits = @"XC_kAXXCAttributeTraits";
|
|
35
36
|
static NSString *const kAttributeChildren = @"XC_kAXXCAttributeChildren";
|
|
36
37
|
static NSString *const kSnapshotAttributes = @"UIAccessibilitySnapshotKeyAttributes";
|
|
37
38
|
static NSString *const kSnapshotChildren = @"UIAccessibilitySnapshotKeyChildren";
|
|
@@ -185,6 +186,11 @@ static void finishRequestWatchdog(dispatch_source_t watchdog, SnapshotWatchdogSt
|
|
|
185
186
|
- (nullable id)jsonValue:(id)value name:(NSString *)name
|
|
186
187
|
{
|
|
187
188
|
if (!value || value == [NSNull null]) return nil;
|
|
189
|
+
// The traits word is a uint64 bit set; JSON numbers lose its high bits past 2^53, a decimal
|
|
190
|
+
// string keeps every bit for the host to parse exactly.
|
|
191
|
+
if ([name isEqualToString:kAttributeTraits] && [value isKindOfClass:NSNumber.class]) {
|
|
192
|
+
return ((NSNumber *)value).stringValue;
|
|
193
|
+
}
|
|
188
194
|
if ([value isKindOfClass:NSString.class] || [value isKindOfClass:NSNumber.class]) return value;
|
|
189
195
|
|
|
190
196
|
const void *raw = (__bridge const void *)value;
|
|
@@ -291,6 +297,7 @@ static void finishRequestWatchdog(dispatch_source_t watchdog, SnapshotWatchdogSt
|
|
|
291
297
|
kAttributeIdentifier,
|
|
292
298
|
kAttributeFrame,
|
|
293
299
|
kAttributeAutomationType,
|
|
300
|
+
kAttributeTraits,
|
|
294
301
|
kAttributeChildren,
|
|
295
302
|
];
|
|
296
303
|
NSArray<NSNumber *> *numbers = _attributeNumbersForNames(names);
|
package/dist/src/adapter.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{C as e,j as t}from"./sdk-contracts.js";import{Br as n,zr as r}from"./sdk-batch.js";import{c as i,r as a}from"./diagnostics.js";import{f as o,x as s}from"./owner-identity.js";import{c,l,m as u,r as d}from"./exec.js";import{t as f}from"./file.js";import"./diagnostics2.js";import"./command.js";import{n as p}from"./retry.js";import{n as m}from"./version.js";import"./process.js";import{C as ee,D as te,c as ne,f as re,h as ie,n as ae,o as oe,w as se,y as ce}from"./host-file.js";import{t as le}from"./apple-runner-platform.js";import{t as ue}from"./snapshot-process.js";import h from"node:path";import{createHash as g,randomUUID as _}from"node:crypto";import de from"node:net";import{Buffer as v}from"node:buffer";const fe={unsupported:`UNSUPPORTED_OPERATION`,"malformed-tree":`COMMAND_FAILED`,"stale-target":`COMMAND_FAILED`,timeout:`COMMAND_FAILED`,cancelled:`COMMAND_FAILED`,"process-crash":`COMMAND_FAILED`,"transport-failure":`COMMAND_FAILED`};var y=class extends e{failureKind;failureCode;constructor(e,t,n=`iOS Simulator snapshot source ${e}: ${t}`,r={},i){super(fe[e],n,{...r,bridgeFailure:e,bridgeFailureCode:t,...e===`cancelled`?{reason:`request_canceled`}:{}},i),this.name=`SnapshotSourceError`,this.failureKind=e,this.failureCode=t}};function b(e,t,n={},r){return new y(e,t,void 0,n,r)}function x(n){return n instanceof y?n:t(n)?b(`cancelled`,`abort-signal`,{},n):n instanceof e&&typeof n.details?.timeoutMs==`number`?b(`timeout`,`host-operation-timeout`,{timeoutMs:n.details.timeoutMs},n):b(`transport-failure`,`unexpected-host-error`,{error:n instanceof Error?n.message:String(n)},n)}function pe(e,t,n=Date.now){if(t?.aborted)throw b(`cancelled`,`abort-signal`);return{clock:p.fromTimeoutMs(e,n()),now:n,signal:t}}function S(e,t){if(e.signal?.aborted)throw b(`cancelled`,`abort-signal`);let n=e.clock.remainingMs(e.now());if(n<=0)throw b(`timeout`,t);return Math.max(1,Math.floor(n))}async function C(e,t,n){let r=Math.min(t,S(e,n));await new Promise((t,n)=>{let i=!1,a=setTimeout(()=>s(t),r),o=()=>{s(()=>n(b(`cancelled`,`abort-signal`)))},s=t=>{i||(i=!0,clearTimeout(a),e.signal?.removeEventListener(`abort`,o),t())};e.signal?.addEventListener(`abort`,o,{once:!0}),e.signal?.aborted&&o()})}const w=[`SnapshotBridge.m`,`SnapshotBridgeRuntime.m`,`SnapshotBridgeRuntime.h`,`SnapshotBridgeCapture.h`,`SnapshotBridgeCapture.m`],me=[`SnapshotBridge.m`,`SnapshotBridgeRuntime.m`,`SnapshotBridgeCapture.m`];async function he(e,t,n){let r=g(`sha256`);for(let i of w){let a=h.join(t,i);if(S(n,`native-source-fingerprint-deadline`),!e.exists(a))throw b(`unsupported`,`native-source-missing`,{filePath:a});r.update(i),r.update(`\0`),r.update(await e.readBinary(a)),r.update(`\0`)}return r.digest(`hex`)}async function ge(e,t,n){let r=await T(e,`xcodebuild`,[`-version`],n),i=await T(e,`sw_vers`,[`-productVersion`],n),a=await T(e,`sw_vers`,[`-buildVersion`],n),o=await T(e,`uname`,[`-m`],n),s=await T(e,`xcrun`,[`--sdk`,`iphonesimulator`,`--show-sdk-version`],n),c=t.trim();if(!c)throw b(`unsupported`,`simulator-runtime-missing`);if(o!==`arm64`&&o!==`x86_64`)throw b(`unsupported`,`simulator-architecture-unsupported`,{architecture:o});return{xcode:r,macosProductVersion:i,macosBuild:a,architecture:o,simulatorSdk:s,simulatorRuntime:c}}async function T(e,t,n,r){let i=await _e(e,t,n,r);if(i.exitCode!==0)throw b(`unsupported`,`toolchain-probe-failed`,{command:t,exitCode:i.exitCode,stderr:i.stderr.slice(0,1024)});let a=(i.stdout||i.stderr).trim();if(!a)throw b(`unsupported`,`toolchain-probe-empty`,{command:t});return a}async function _e(e,t,n,r){try{return await E(e,t,n,r)}catch(i){if(!d(i))throw i;if(r.signal?.aborted)throw b(`cancelled`,`abort-signal`);if(r.clock.remainingMs(r.now())<=0)throw i;return await E(e,t,n,r)}}function E(e,t,n,r){return e.run(t,n,{allowFailure:!0,signal:r.signal,timeoutMs:Math.min(le,S(r,`toolchain-probe-deadline`))})}const D=`agent-device-simulator-ax-v1.5.5`;Object.freeze([`verb`,`requestId`,`pid`,`generation`,`snapshotTree`,`automationMode`,`maxDepth`,`maxNodes`,`maxDurationMs`,`maxResponseBytes`,`nativeLevelsHint`]),Object.freeze([`protocolVersion`,`sourceVersion`,`requestId`,`generation`,`ok`,`pid`,`tree`,`truncated`,`automationEnabled`,`recovery`,`error_kind`,`error_code`,`error`]),Object.freeze([`XC_kAXXCAttributeElementType`,`XC_kAXXCAttributeElementBaseType`,`XC_kAXXCAttributeLabel`,`XC_kAXXCAttributeValue`,`XC_kAXXCAttributeIdentifier`,`XC_kAXXCAttributeFrame`,`XC_kAXXCAttributeAutomationType`,`XC_kAXXCAttributeChildren`]);const ve=[`requests`,`rejected`,`continuations`,`acceptedLevels`];function ye(e){let t=e.recovery;if(!P(t))throw b(`malformed-tree`,`recovery-invalid`);let n=ve.map(e=>[e,t[e]]);if(n.some(([,e])=>!Number.isSafeInteger(e)||e<0))throw b(`malformed-tree`,`recovery-invalid`);return Object.freeze(Object.fromEntries(n))}function be(e,t){let n;try{n=v.from(JSON.stringify(e),`utf8`)}catch(e){throw b(`malformed-tree`,`request-not-json`,{},e)}let r=n.length+4;if(r>t.maxRequestBytes)throw b(`transport-failure`,`request-limit-exceeded`,{frameBytes:r,maxRequestBytes:t.maxRequestBytes});let i=v.alloc(4);return i.writeUInt32BE(n.length,0),v.concat([i,n])}var O=class{header=v.alloc(4);headerBytes=0;chunks=[];payloadBytes=0;expectedBodyBytes;frame;maxFrameBytes;constructor(e){if(!Number.isSafeInteger(e)||e<=0)throw b(`malformed-tree`,`frame-limit-invalid`,{maxFrameBytes:e});this.maxFrameBytes=e}push(e){if(this.frame)return this.acceptTrailingChunk(e);let t=this.readHeader(e);if(t&&(this.appendPayload(e,t.offset,t.bodyBytes),this.payloadBytes===t.bodyBytes))return this.frame=v.concat(this.chunks,t.bodyBytes),this.frame}acceptTrailingChunk(e){if(e.length>0)throw b(`malformed-tree`,`multiple-frames`,{trailingBytes:e.length});return this.frame}readHeader(e){if(this.headerBytes===4)return{offset:0,bodyBytes:this.expectedBodyBytes};let t=Math.min(4-this.headerBytes,e.length);if(e.copy(this.header,this.headerBytes,0,t),this.headerBytes+=t,this.headerBytes<4)return;let n=this.header.readUInt32BE(0);if(n===0||n>this.maxFrameBytes)throw b(`malformed-tree`,`frame-limit-exceeded`,{bodyBytes:n,maxFrameBytes:this.maxFrameBytes});return this.expectedBodyBytes=n,{offset:t,bodyBytes:n}}appendPayload(e,t,n){let r=n-this.payloadBytes,i=e.length-t;if(i>r)throw b(`malformed-tree`,`multiple-frames`,{trailingBytes:i-r});i!==0&&(this.chunks.push(e.subarray(t)),this.payloadBytes+=i)}finish(){if(this.frame)return this.frame;throw b(`transport-failure`,`bridge-frame-incomplete`,{headerBytes:this.headerBytes,payloadBytes:this.payloadBytes,expectedBodyBytes:this.expectedBodyBytes})}};function k(e){let t;try{t=JSON.parse(e.toString(`utf8`))}catch(e){throw b(`malformed-tree`,`response-not-json`,{},e)}if(!P(t))throw b(`malformed-tree`,`response-not-object`);return t}function A(e){return Object.freeze({verb:`describe`,requestId:e.requestId,pid:e.pid,generation:e.generation,snapshotTree:!0,automationMode:!0,maxDepth:e.maxDepth,maxNodes:e.maxNodes,maxDurationMs:e.maxDurationMs,maxResponseBytes:e.maxResponseBytes,...e.nativeLevelsHint===void 0?{}:{nativeLevelsHint:e.nativeLevelsHint}})}function j(e,t){if(e.protocolVersion!==1)throw b(`transport-failure`,`protocol-version-mismatch`,{expected:1,observed:e.protocolVersion});if(e.sourceVersion!==`agent-device-simulator-ax-v1.5.5`)throw b(`transport-failure`,`source-version-mismatch`,{expected:D,observed:e.sourceVersion});if(e.requestId!==t)throw b(`transport-failure`,`request-id-mismatch`,{expected:t,observed:e.requestId})}function M(e,t){if(typeof e.pid!=`number`||e.pid!==t.pid)throw b(`stale-target`,`bridge-pid-mismatch`,{expectedPid:t.pid,observedPid:e.pid});if(e.generation!==t.generation)throw b(`stale-target`,`bridge-generation-mismatch`,{expectedGeneration:t.generation,observedGeneration:e.generation})}function N(e){let t=e.error_kind,n=typeof e.error_code==`string`?e.error_code:`guest-error`,r=typeof e.error==`string`?e.error:void 0,i=r?{guestMessage:r.slice(0,1024)}:{};throw b(t===`unsupported`?`unsupported`:t===`malformed_tree`?`malformed-tree`:t===`application_not_responding`?`timeout`:t===`application_unavailable`?`transport-failure`:t===`bad_request`?`malformed-tree`:`transport-failure`,n,i)}function P(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}const F=`snapshot-bridge`,I=`manifest.json`;async function xe(e){let t=e.deadline,n=e.sourceRoot??Se(e.host),r=await he(e.host,n,t),i=await ge(e.host,e.runtime,t),a=we({schemaVersion:1,protocolVersion:1,sourceVersion:D,sourceHash:r,toolchain:i}),o=e.cacheRoot??h.join(e.host.homeDirectory(),`.agent-device`,`snapshot-source`),s=h.join(o,a),c=await e.host.acquireLock(h.join(o,`${a}.lock`),{deadline:t});try{let c=await Ce(e.host,s,{sourceHash:r,cacheKey:a,toolchain:i},t);if(c)return c;S(t,`native-build-deadline`),e.host.exists(s)&&await e.host.remove(s),S(t,`native-build-deadline`),await e.host.ensureDirectory(o);let l=h.join(o,`.${a}.${e.host.processId()}.tmp`);S(t,`native-build-deadline`),await e.host.remove(l);try{S(t,`native-build-deadline`),await e.host.ensureDirectory(l);let o=h.join(l,F),c=await e.host.run(`xcrun`,[`--sdk`,`iphonesimulator`,`clang`,`-arch`,i.architecture,`-mios-simulator-version-min=15.0`,`-fobjc-arc`,`-Werror`,`-Wall`,`-Wextra`,`-framework`,`Foundation`,`-framework`,`CoreGraphics`,...me.map(e=>h.join(n,e)),`-o`,o],{signal:t.signal,timeoutMs:Math.min(12e4,S(t,`native-build-deadline`)),allowFailure:!0});if(c.exitCode!==0||!e.host.exists(o))throw b(`unsupported`,`native-build-failed`,{exitCode:c.exitCode,stderr:c.stderr.slice(0,4096)});S(t,`native-build-deadline`),await e.host.chmod(o,493);let u=await L(e.host,o,t),d={schemaVersion:1,protocolVersion:1,sourceVersion:D,sourceHash:r,cacheKey:a,toolchain:i,binarySha256:u};return await e.host.writeText(h.join(l,I),`${JSON.stringify(d,null,2)}\n`),S(t,`native-build-deadline`),await e.host.rename(l,s),{path:h.join(s,F),sourceHash:r,cacheKey:a,protocolVersion:1,sourceVersion:D}}catch(t){throw await e.host.remove(l),t}}finally{await c()}}function Se(e){let t=e.projectRoot(),n=h.join(t,`apple`,`snapshot-bridge`);if(w.every(t=>e.exists(h.join(n,t))))return n;let r=h.join(t,`dist`,`apple`,`snapshot-bridge`);if(w.every(t=>e.exists(h.join(r,t))))return r;throw b(`unsupported`,`native-source-missing`,{projectRoot:t})}async function Ce(e,t,n,r){let i=h.join(t,F);if(!(!e.exists(i)||!e.exists(h.join(t,I))))try{let a=JSON.parse(await e.readText(h.join(t,I)));return a.schemaVersion!==1||a.protocolVersion!==1||a.sourceVersion!==`agent-device-simulator-ax-v1.5.5`||a.sourceHash!==n.sourceHash||a.cacheKey!==n.cacheKey||JSON.stringify(a.toolchain)!==JSON.stringify(n.toolchain)||typeof a.binarySha256!=`string`||await L(e,i,r)!==a.binarySha256?void 0:{path:i,sourceHash:n.sourceHash,cacheKey:n.cacheKey,protocolVersion:1,sourceVersion:D}}catch(e){if(e instanceof y&&(e.failureKind===`cancelled`||e.failureKind===`timeout`))throw e;return}}async function L(e,t,n){return S(n,`native-cache-hash-deadline`),g(`sha256`).update(await e.readBinary(t)).digest(`hex`)}function we(e){return g(`sha256`).update(JSON.stringify(e)).digest(`hex`).slice(0,32)}var Te=class{entries=new Map;probeBackAfterUses;constructor(e=8){this.probeBackAfterUses=e}consume(e,t,n){if(n)return{nativeLevels:void 0,reason:`explicit-depth`};let r=this.currentEntry(e);return r===`unidentified`?{nativeLevels:void 0,reason:`unidentified-target`}:!r||r.nativeLevels>=t?{nativeLevels:void 0,reason:`no-hint`}:r.remainingUses<=0?{nativeLevels:void 0,reason:`probe-back`}:(--r.remainingUses,{nativeLevels:r.nativeLevels,reason:`hinted`})}learn(e,t,n,r){return n||!e.targetId?`ignored`:r.rejected>0&&r.acceptedLevels<t?(this.remember(e.targetId,{generation:e.generation,nativeLevels:r.acceptedLevels,remainingUses:this.probeBackAfterUses}),`learned`):r.rejected===0&&r.acceptedLevels>=t?this.entries.delete(e.targetId)?`forgotten`:`ignored`:this.currentEntry(e)?`kept`:`ignored`}currentEntry(e){if(!e.targetId)return`unidentified`;let t=this.entries.get(e.targetId);if(t){if(t.generation!==e.generation){this.entries.delete(e.targetId);return}return t}}remember(e,t){if(this.entries.delete(e),this.entries.size>=32){let e=this.entries.keys().next().value;e!==void 0&&this.entries.delete(e)}this.entries.set(e,t)}};const R=65536;function Ee(){return{projectRoot:m,homeDirectory:re,run:async(e,t,n)=>await c(e,t,n),start:De,connect:z,readText:ce,readBinary:ie,writeText:te,ensureDirectory:oe,chmod:ae,exists:ne,rename:se,remove:ee,acquireLock:Oe,emitDiagnostic:a,withDiagnosticTimer:i,processId:o,readTargetProcessStartTime:ue}}function De(e,t,n,r={}){if(r.signal?.aborted)throw b(`cancelled`,`abort-signal`);let i=l(`xcrun`,[`simctl`,`spawn`,e,t,`serve`,n,`--idle-timeout`,`60`,`--exit-on-disconnect`,`false`],{allowFailure:!0,captureOutput:!1,detached:!0}),a=i.child.pid??0;if(a<=0)throw b(`transport-failure`,`bridge-process-pid-missing`);let o=``;return i.child.stderr?.setEncoding(`utf8`),i.child.stderr?.on(`data`,e=>{o=ke(o,String(e))}),{pid:a,wait:i.wait,isAlive:()=>i.child.exitCode===null&&i.child.signalCode===null,signal:e=>{u(a,e)||i.child.kill(e)},readLog:()=>o}}async function z(e,t){if(t.signal?.aborted)throw b(`cancelled`,`abort-signal`);let n=Math.max(1,Math.floor(t.timeoutMs));return await new Promise((r,i)=>{let a=de.createConnection({path:e}),o=!1,s=!1,c=setTimeout(()=>{p(b(`timeout`,`bridge-connect-timeout`)),a.destroy()},n),l=()=>{p(b(`cancelled`,`abort-signal`)),a.destroy()},u=()=>{o=!0,clearTimeout(c),t.signal?.removeEventListener(`abort`,l),a.off(`error`,d),a.off(`close`,f),a.setTimeout(0),r(a)},d=e=>{p(e),a.destroy()},f=()=>{o||p(b(`transport-failure`,`bridge-closed-before-connect`))},p=e=>{s||o||(s=!0,clearTimeout(c),t.signal?.removeEventListener(`abort`,l),a.off(`connect`,u),a.off(`error`,d),a.off(`close`,f),i(e))};a.once(`connect`,u),a.once(`error`,d),a.once(`close`,f),t.signal?.addEventListener(`abort`,l,{once:!0}),t.signal?.aborted&&l()})}async function Oe(e,t){let n=o(),r=t.deadline,i=f({lockDirPath:e,owner:{pid:n,startTime:s(n),acquiredAtMs:Date.now()},timeoutMs:S(r,`cache-lock-deadline`),pollMs:100,ownerGraceMs:5e3,description:`iOS Simulator snapshot bridge cache`}),a=r.signal;if(!a)return await i;let c=!1,l,u=new Promise((e,t)=>{l=()=>{c=!0,t(b(`cancelled`,`abort-signal`))},a.addEventListener(`abort`,l,{once:!0}),a.aborted&&l()});try{return await Promise.race([i,u])}catch(e){throw c&&i.then(e=>e(),()=>void 0),r.clock.isExpired()&&!(e instanceof y&&e.failureKind===`cancelled`)?b(`timeout`,`cache-lock-deadline`):e}finally{a.removeEventListener(`abort`,l)}}function ke(e,t){let n=e+t;return n.length<=R?n:n.slice(n.length-R)}function Ae(e,t,n){let r=g(`sha256`).update(t).digest(`hex`).slice(0,12),i=g(`sha256`).update(n).digest(`hex`).slice(0,12);return h.join(`/tmp`,`agent-device-ax-${r}-${e.processId()}-${i}`,`snapshot.sock`)}const B=new WeakSet;async function V(e,t){let n;try{n=(await t.wait).exitCode}catch{n=void 0}return B.has(t)||(B.add(t),e.emitDiagnostic({level:`error`,phase:`ios.snapshot-source.bridge-process-exit`,data:{pid:t.pid,...n===void 0?{}:{exitCode:n},stderr:je(t.readLog())}})),b(`process-crash`,`bridge-exited`,{pid:t.pid,...n===void 0?{}:{exitCode:n}})}function je(e){let t=v.from(e);return t.length<=65536?e:t.subarray(-65536).toString(`utf8`)}async function Me(e){let t=new O(e.limits.maxResponseBytes-4),n=S(e.deadline,`bridge-request-deadline`);return await new Promise((r,i)=>{let a=!1,o=!1,s=setTimeout(()=>{p(b(`timeout`,`bridge-request-deadline`,{dispatched:o})),e.socket.destroy()},n),c=()=>{p(b(`cancelled`,`abort-signal`,{dispatched:o})),e.socket.destroy()},l=n=>{try{if(!Buffer.isBuffer(n))throw b(`transport-failure`,`bridge-data-invalid`);let r=t.push(n);if(r){let t=k(r);if(j(t,e.requestId),M(t,{pid:e.expectedPid,generation:e.expectedGeneration}),t.ok!==!0&&N(t),typeof t.truncated!=`boolean`)throw b(`malformed-tree`,`truncated-invalid`);f(t);return}}catch(t){p(t),e.socket.destroy()}},u=e=>p(x(e)),d=()=>{a||(e.process.isAlive()?p(b(`transport-failure`,`bridge-connection-closed`)):V(e.host,e.process).then(p))};e.process.wait.then(()=>{a||V(e.host,e.process).then(p)},e=>{a||p(x(e))});let f=e=>m(()=>r(e)),p=e=>m(()=>i(e)),m=t=>{a||(a=!0,clearTimeout(s),e.deadline.signal?.removeEventListener(`abort`,c),e.socket.off(`data`,l),e.socket.off(`error`,u),e.socket.off(`close`,d),t())};e.socket.on(`data`,l),e.socket.on(`error`,u),e.socket.on(`close`,d),e.deadline.signal?.addEventListener(`abort`,c,{once:!0});try{if(e.deadline.signal?.aborted)throw b(`cancelled`,`abort-signal`);o=!0,e.socket.write(e.frame)}catch(t){p(x(t)),e.socket.destroy()}})}var Ne=class{sessions=new Map;requestQueues=new Map;ownerId=_();closed=!1;host;constructor(e){this.host=e}async request(e){if(this.closed)throw b(`unsupported`,`source-closed`);return await this.withSimulatorLock(e.target.udid,e.deadline,()=>this.requestInSimulator(e))}async requestInSimulator(e){if(this.closed)throw b(`unsupported`,`source-closed`);let t=e.deadline;S(t,`bridge-request-deadline`);let n=this.sessions.get(e.target.udid),r=await this.ensureSession(e,t);try{let n=await this.readTargetStartTime(e.target,t),i=await this.exchange(r,e,t);return await this.assertTargetStillCurrent(e.target,n,t),i}catch(e){throw await this.handleRequestFailure(e,r,n)}}async handleRequestFailure(e,t,n){let r=x(e);return Fe(r,t,n)?await this.removeSession(t,!0):r.failureKind===`process-crash`?await this.removeSession(t,!1):r.failureKind===`transport-failure`&&(t.socket?.destroy(),t.socket=void 0),r}async withSimulatorLock(e,t,n){let r=this.requestQueues.get(e)??Promise.resolve(),i,a=new Promise(e=>{i=e}),o=r.then(()=>a);this.requestQueues.set(e,o);try{return await Pe(r,t),await n()}finally{i(),this.requestQueues.get(e)===o&&this.requestQueues.delete(e)}}async close(){if(this.closed)return;this.closed=!0;let e=[...this.sessions.values()];this.sessions.clear(),await Promise.all(e.map(async e=>await this.dispose(e,!0)))}async ensureSession(e,t){let n=e.target.udid,r=this.sessions.get(n);if(r&&r.bridgePath===e.bridge.path&&r.process.isAlive())return(!r.socket||r.socket.destroyed)&&(r.socket=await this.connectUntilReady(r,t)),r;r&&await this.removeSession(r,!0);let i=Ae(this.host,e.target.udid,this.ownerId);await this.host.ensureDirectory(h.dirname(i)),await this.host.remove(i);let a=this.host.start(e.target.udid,e.bridge.path,i,{signal:t.signal}),o={udid:e.target.udid,bridgePath:e.bridge.path,socketPath:i,process:a};this.sessions.set(n,o);try{return o.socket=await this.connectUntilReady(o,t),o}catch(e){throw await this.removeSession(o,!0),x(e)}}async connectUntilReady(e,t){let n;for(;;){let r=S(t,`bridge-connect-deadline`);if(!e.process.isAlive())throw await V(this.host,e.process);try{return await this.host.connect(e.socketPath,{signal:t.signal,timeoutMs:Math.min(250,r)})}catch(e){if(n=e,e instanceof y&&e.failureKind===`cancelled`)throw e;let r=Math.min(20,S(t,`bridge-connect-deadline`));try{await C(t,r,`bridge-connect-deadline`)}catch(e){throw x(e)}}if(n instanceof y&&n.failureKind===`timeout`)throw n}}async exchange(e,t,n){(!e.socket||e.socket.destroyed)&&(e.socket=await this.connectUntilReady(e,n));let r=_(),i=be(A({requestId:r,pid:t.target.pid,generation:t.target.generation,maxDepth:Math.min(t.limits.maxTraversalDepth,t.maxDepth),maxNodes:t.limits.maxNodes,maxDurationMs:S(n,`bridge-request-deadline`),maxResponseBytes:t.limits.maxResponseBytes,...t.nativeLevelsHint===void 0?{}:{nativeLevelsHint:t.nativeLevelsHint}}),t.limits);return await Me({process:e.process,socket:e.socket,frame:i,requestId:r,deadline:n,limits:t.limits,expectedPid:t.target.pid,expectedGeneration:t.target.generation,host:this.host})}async readTargetStartTime(e,t){let n=await this.host.readTargetProcessStartTime(e.pid,{signal:t.signal,timeoutMs:S(t,`target-identity-deadline`)});if(!n)throw b(`stale-target`,`target-process-unavailable`,{pid:e.pid,generation:e.generation});if(e.processStartTime!==void 0&&e.processStartTime!==n)throw b(`stale-target`,`target-process-changed`,{pid:e.pid,generation:e.generation,expectedStartTime:e.processStartTime,observedStartTime:n});return n}async assertTargetStillCurrent(e,t,n){let r=await this.host.readTargetProcessStartTime(e.pid,{signal:n.signal,timeoutMs:S(n,`target-identity-deadline`)});if(r!==t)throw b(`stale-target`,`target-process-changed`,{pid:e.pid,generation:e.generation,expectedStartTime:t,observedStartTime:r})}async removeSession(e,t){this.sessions.get(e.udid)===e&&this.sessions.delete(e.udid),await this.dispose(e,t)}async dispose(e,t){e.socket?.destroy(),e.socket=void 0,t&&e.process.isAlive()&&(e.process.signal(`SIGTERM`),await H(e.process,500),e.process.isAlive()&&(e.process.signal(`SIGKILL`),await H(e.process,500))),await this.host.remove(e.socketPath)}};async function Pe(e,t){let n=S(t,`bridge-request-deadline`);await Promise.race([e,C(t,n,`bridge-request-deadline`).then(()=>{throw b(`timeout`,`bridge-request-deadline`)})])}function Fe(e,t,n){return(e.failureKind===`cancelled`||e.failureKind===`timeout`)&&(e.details?.dispatched===!0||n!==t)}async function H(e,t){await Promise.race([e.wait.catch(()=>void 0),new Promise(e=>setTimeout(e,t))])}const U=16777216,W=12e4,G=1e4,Ie=Object.freeze({maxRequestBytes:65536,maxResponseBytes:4194304,maxNodes:5e3,maxTraversalDepth:64,maxDurationMs:5e3});function Le(t){let n={...Ie,...t??{}};for(let[t,r]of Object.entries(n))if(!Number.isSafeInteger(r)||r<=0)throw new e(`INVALID_ARGS`,`Snapshot source limit ${t} must be a positive integer`,{name:t,value:r});if(n.maxRequestBytes>n.maxResponseBytes)throw new e(`INVALID_ARGS`,`Snapshot source request bytes cannot exceed response bytes`,{maxRequestBytes:n.maxRequestBytes,maxResponseBytes:n.maxResponseBytes});if(n.maxRequestBytes>U||n.maxResponseBytes>U)throw new e(`INVALID_ARGS`,`Snapshot source frame limits exceed the bridge bound`,{maxRequestBytes:n.maxRequestBytes,maxResponseBytes:n.maxResponseBytes,maximumFrameBytes:U});if(n.maxNodes>G||n.maxTraversalDepth>128)throw new e(`INVALID_ARGS`,`Snapshot source tree limits exceed the bridge bound`,{maxNodes:n.maxNodes,maxTraversalDepth:n.maxTraversalDepth,maximumNodes:G,maximumDepth:128});if(n.maxDurationMs>W)throw new e(`INVALID_ARGS`,`Snapshot source duration exceeds the bridge bound`,{maxDurationMs:n.maxDurationMs,maximumDurationMs:W});if(n.maxRequestBytes<=4||n.maxResponseBytes<=4)throw new e(`INVALID_ARGS`,`Snapshot source frame limits must leave room for a body`,{maxRequestBytes:n.maxRequestBytes,maxResponseBytes:n.maxResponseBytes});return Object.freeze(n)}const K=Object.freeze({elementType:`XC_kAXXCAttributeElementType`,elementBaseType:`XC_kAXXCAttributeElementBaseType`,label:`XC_kAXXCAttributeLabel`,value:`XC_kAXXCAttributeValue`,identifier:`XC_kAXXCAttributeIdentifier`,frame:`XC_kAXXCAttributeFrame`,automationType:`XC_kAXXCAttributeAutomationType`,children:`XC_kAXXCAttributeChildren`}),q=`Other.Other.Application.Group.Window.Sheet.Drawer.Alert.Dialog.Button.RadioButton.RadioGroup.CheckBox.DisclosureTriangle.PopUpButton.ComboBox.MenuButton.ToolbarButton.Popover.Keyboard.Key.NavigationBar.TabBar.TabGroup.Toolbar.StatusBar.Table.TableRow.TableColumn.Outline.OutlineRow.Browser.CollectionView.Slider.PageIndicator.ProgressIndicator.ActivityIndicator.SegmentedControl.Picker.PickerWheel.Switch.Toggle.Link.Image.Icon.SearchField.ScrollView.ScrollBar.StaticText.TextField.SecureTextField.DatePicker.TextView.Menu.MenuItem.MenuBar.MenuBarItem.Map.WebView.IncrementArrow.DecrementArrow.Timeline.RatingIndicator.ValueIndicator.SplitGroup.Splitter.RelevanceIndicator.ColorWell.HelpTag.Matte.DockItem.Ruler.RulerMarker.Grid.LevelIndicator.Cell.LayoutArea.LayoutItem.Handle.Stepper.Tab.TouchBar.StatusItem`.split(`.`),J={UIApplication:`Application`,UIWindow:`Window`},Re=new Set(Object.values(K));function ze(e,t,n){let r=Array.isArray(e)?e:[e];if(r.length===0||r.some(e=>!P(e)))throw b(`malformed-tree`,`guest-tree-root-invalid`);let i=[],a=[],o=0;for(let e of r)c(e,void 0,0,!1);if(i.length>n.maxNodes)throw b(`malformed-tree`,`node-limit-exceeded`,{nodeCount:i.length,maxNodes:n.maxNodes});if(o>n.maxTraversalDepth)throw b(`malformed-tree`,`traversal-depth-exceeded`,{maxTraversalDepth:o,maxAllowedDepth:n.maxTraversalDepth});if(typeof t.truncated!=`boolean`)throw b(`malformed-tree`,`truncated-invalid`);let s=We(i.find(e=>e.type===`Application`||e.type===`Window`));return{nodes:i,maxTraversalDepth:o,viewport:s,opaqueRemoteElements:a.filter(e=>He(e,s)).length};function c(e,t,r,s){if(i.length>=n.maxNodes)throw b(`malformed-tree`,`node-limit-exceeded`,{maxNodes:n.maxNodes});for(let t of Object.keys(e))if(!Re.has(t))throw b(`malformed-tree`,`node-contains-unknown-field`,{key:t});let l=e[K.children];if(!Array.isArray(l))throw b(`malformed-tree`,`children-invalid`);let u=i.length,d=Be(e,u,t,r);i.push(d),o=Math.max(o,r),Ve(d,l.length,s)&&a.push(d.rect);let f=s||d.type===`WebView`;for(let e of l){if(!P(e))throw b(`malformed-tree`,`child-invalid`);c(e,u,r+1,f)}}}function Be(e,t,n,r){let i=X(e[K.elementType]),a=X(e[K.elementBaseType]),o=Ge(e[K.automationType]),s=Ue(e[K.frame]);return{index:t,...n===void 0?{}:{parentIndex:n},...Y(i,o)?{type:Y(i,o)}:{},...i?{role:i}:{},...a&&a!==i?{subrole:a}:{},...X(e[K.label])?{label:X(e[K.label])}:{},...Z(e[K.value])?{value:Z(e[K.value])}:{},...X(e[K.identifier])?{identifier:X(e[K.identifier])}:{},...s?{rect:s}:{},depth:r}}function Y(e,t){if(e!==void 0&&J[e])return J[e];if(e!==void 0&&q.includes(e))return e;if(t!==void 0)return q[t]??`Other`}function Ve(e,t,n){return n&&e.role===`AXRemoteElement`&&t===0}function He(e,t){return e===void 0?!0:r(e)?t.kind!==`reported`||n(e,t.rect):!1}function Ue(e){if(e===void 0)return;if(!P(e))throw b(`malformed-tree`,`frame-invalid`);let t=[`X`,`Y`,`Width`,`Height`].map(t=>e[t]);if(!t.every(e=>typeof e==`number`&&Number.isFinite(e)))throw b(`malformed-tree`,`frame-invalid`);let[n,r,i,a]=t;if(i<0||a<0)throw b(`malformed-tree`,`frame-invalid`);return{x:n,y:r,width:i,height:a}}function We(e){return!e||e.type!==`Application`&&e.type!==`Window`?{kind:`missing`,reason:`not-provided`}:r(e.rect)?{kind:`reported`,rect:e.rect}:{kind:`missing`,reason:e.rect?`invalid`:`not-provided`}}function X(e){return typeof e==`string`&&e.length>0?e:void 0}function Z(e){if(typeof e==`string`)return e.length>0?e:void 0;if(typeof e==`number`||typeof e==`boolean`)return String(e);if(e!=null)throw b(`malformed-tree`,`scalar-invalid`)}function Ge(e){if(e!=null){if(!Number.isSafeInteger(e))throw b(`malformed-tree`,`automation-type-invalid`);return e}}const Q=`simulator-ax-bridge`;function Ke(e={}){let t=e.host??Ee(),n=new Ne(t),r=new Te,i=new Map,a=!1,o=async n=>{if(a)throw b(`unsupported`,`source-closed`);let r=i.get(n.runtime);if(r)return r;let o=await t.withDiagnosticTimer(`ios.snapshot-source.prepare`,async()=>await xe({host:t,runtime:n.runtime,limits:n.limits,deadline:n.deadline,sourceRoot:e.sourceRoot,cacheRoot:e.cacheRoot}),{producer:Q});return i.set(n.runtime,o),o};return{acquire:async i=>{try{if(a)throw b(`unsupported`,`source-closed`);qe(i);let s=Le({...e.limits,...i.limits}),c=pe(s.maxDurationMs,i.signal),l=Ye(i.hint,s.maxTraversalDepth),u=l+1,d=i.hint.rawTraversalDepth!==null;return await t.withDiagnosticTimer(`ios.snapshot-source.acquire`,async()=>{let e=await o({runtime:i.target.runtime,limits:s,deadline:c}),a=r.consume(i.target,u,d),f=await n.request({target:i.target,bridge:e,limits:s,maxDepth:l,nativeLevelsHint:a.nativeLevels,deadline:c});S(c,`snapshot-decode-deadline`);let p=Xe(i.hint,i.target,f,s);return Je(t,r,i.target,u,d,a,f),{stage:`acquired`,acquisition:p}},{producer:Q})}catch(e){let t=x(e);return{stage:`failed`,failure:{kind:t.failureKind,code:t.failureCode,...t.details?{details:t.details}:{}}}}},close:async()=>{a||(a=!0,await n.close())}}}function qe(t){if(!t.target.udid.trim()||!t.target.runtime.trim()||!t.target.generation.trim()||!Number.isSafeInteger(t.target.pid)||t.target.pid<=0)throw new e(`INVALID_ARGS`,`Simulator snapshot source target identity is incomplete`);let n=t.hint;if(n.projection!==`raw`&&n.projection!==`regular`||![`full`,`surface-observation`].includes(n.acquisitionIntent)||typeof n.interactiveOnly!=`boolean`||typeof n.customActions!=`boolean`||!$(n.rawTraversalDepth)||!$(n.regularPresentedDepth))throw new e(`INVALID_ARGS`,`Simulator snapshot source capture hint is invalid`)}function Je(e,t,n,r,i,a,o){let s=ye(o),c=o.truncated===!0,l=t.learn(n,r,i,s);e.emitDiagnostic({level:`debug`,phase:`ios_snapshot_source_recovery`,data:{producer:Q,...n.targetId?{targetId:n.targetId}:{},generation:n.generation,requestedLevels:r,hint:a.reason,...a.nativeLevels===void 0?{}:{hintedLevels:a.nativeLevels},...s,truncated:c,learning:l}})}function Ye(t,n){let r=t.rawTraversalDepth??n;if(r>n)throw new e(`INVALID_ARGS`,`Simulator snapshot source depth exceeds its bound`,{requested:r,maximum:n});return r}function $(e){return e===null||Number.isSafeInteger(e)&&e>=0}function Xe(e,t,n,r){if(n.automationEnabled!==!0)throw b(`unsupported`,`automation-mode-unavailable`);let i=n.tree,a=n.truncated;if(typeof a!=`boolean`)throw b(`malformed-tree`,`truncated-invalid`);let o=ze(i,{truncated:a},r),s=n.generation;if(typeof s!=`string`||!s)throw b(`malformed-tree`,`generation-invalid`);if(o.opaqueRemoteElements>0)throw b(`unsupported`,`remote-content-boundary`,{remoteElements:o.opaqueRemoteElements});let c=Object.freeze(o.nodes.map(e=>Object.freeze({...e,pid:t.pid}))),l=Ze(e,a,o.viewport),u=Object.freeze({...t.targetId?{targetId:t.targetId}:{},generation:s}),d={producer:Q,nodes:c,truncated:a,viewport:o.viewport,lineage:u,residue:l};return e.acquisitionIntent===`full`?{...d,intent:`full`,hint:{...e,acquisitionIntent:`full`}}:{...d,intent:`surface-observation`,hint:{...e,acquisitionIntent:`surface-observation`}}}function Ze(e,t,n){return Object.freeze([{kind:`unavailable-fact`,fact:`hittability`},...e.interactiveOnly?[{kind:`unavailable-fact`,fact:`interactive-query`}]:[],...t?[{kind:`truncated`}]:[],...n.kind===`missing`?[{kind:`missing-viewport`,reason:n.reason}]:[]])}export{Ke as createSimulatorSnapshotSource};
|
|
1
|
+
import{C as e,j as t}from"./sdk-contracts.js";import{Br as n,zr as r}from"./sdk-batch.js";import{c as i,r as a}from"./diagnostics.js";import{f as o,x as s}from"./owner-identity.js";import{c,l,m as u,r as d}from"./exec.js";import{n as f,t as p}from"./file.js";import"./diagnostics2.js";import"./command.js";import{n as m}from"./retry.js";import{n as ee}from"./version.js";import"./process.js";import{C as te,D as ne,c as re,f as ie,h as ae,n as oe,o as se,w as ce,y as le}from"./host-file.js";import{t as h}from"./apple-runner-platform.js";import{n as ue,r as de,t as fe}from"./snapshot-process.js";import g from"node:path";import{createHash as _,randomUUID as v}from"node:crypto";import pe from"node:net";import{Buffer as y}from"node:buffer";const me={unsupported:`UNSUPPORTED_OPERATION`,"malformed-tree":`COMMAND_FAILED`,"stale-target":`COMMAND_FAILED`,timeout:`COMMAND_FAILED`,cancelled:`COMMAND_FAILED`,"process-crash":`COMMAND_FAILED`,"transport-failure":`COMMAND_FAILED`,preparing:`COMMAND_FAILED`};var b=class extends e{failureKind;failureCode;constructor(e,t,n=`iOS Simulator snapshot source ${e}: ${t}`,r={},i){super(me[e],n,{...r,bridgeFailure:e,bridgeFailureCode:t,...e===`cancelled`?{reason:`request_canceled`}:{}},i),this.name=`SnapshotSourceError`,this.failureKind=e,this.failureCode=t}};function x(e,t,n={},r){return new b(e,t,void 0,n,r)}function S(n){return n instanceof b?n:t(n)?x(`cancelled`,`abort-signal`,{},n):n instanceof e&&typeof n.details?.timeoutMs==`number`?x(`timeout`,`host-operation-timeout`,{timeoutMs:n.details.timeoutMs},n):x(`transport-failure`,`unexpected-host-error`,{error:n instanceof Error?n.message:String(n)},n)}function C(e,t,n=Date.now){if(t?.aborted)throw x(`cancelled`,`abort-signal`);return{clock:m.fromTimeoutMs(e,n()),now:n,signal:t}}function w(e,t){if(e.signal?.aborted)throw x(`cancelled`,`abort-signal`);let n=e.clock.remainingMs(e.now());if(n<=0)throw x(`timeout`,t);return Math.max(1,Math.floor(n))}async function T(e,t,n,r){let i=Math.min(t,w(e,n));await de({waitMs:i,signal:e.signal,stop:r,cancelled:()=>x(`cancelled`,`abort-signal`)})}var he=class{entries=new Map;probeBackAfterUses;constructor(e=8){this.probeBackAfterUses=e}consume(e,t,n){if(n)return{nativeLevels:void 0,reason:`explicit-depth`};let r=this.currentEntry(e);return r===`unidentified`?{nativeLevels:void 0,reason:`unidentified-target`}:!r||r.nativeLevels>=t?{nativeLevels:void 0,reason:`no-hint`}:r.remainingUses<=0?{nativeLevels:void 0,reason:`probe-back`}:(--r.remainingUses,{nativeLevels:r.nativeLevels,reason:`hinted`})}learn(e,t,n,r){return n||!e.targetId?`ignored`:r.rejected>0&&r.acceptedLevels<t?(this.remember(e.targetId,{generation:e.generation,nativeLevels:r.acceptedLevels,remainingUses:this.probeBackAfterUses}),`learned`):r.rejected===0&&r.acceptedLevels>=t?this.entries.delete(e.targetId)?`forgotten`:`ignored`:this.currentEntry(e)?`kept`:`ignored`}currentEntry(e){if(!e.targetId)return`unidentified`;let t=this.entries.get(e.targetId);if(t){if(t.generation!==e.generation){this.entries.delete(e.targetId);return}return t}}remember(e,t){if(this.entries.delete(e),this.entries.size>=32){let e=this.entries.keys().next().value;e!==void 0&&this.entries.delete(e)}this.entries.set(e,t)}};const E=65536;function ge(){return{projectRoot:ee,homeDirectory:ie,run:async(e,t,n)=>await c(e,t,n),start:_e,connect:ve,readText:le,readBinary:ae,writeText:ne,ensureDirectory:se,chmod:oe,exists:re,rename:ce,remove:te,acquireLock:ye,emitDiagnostic:a,withDiagnosticTimer:i,processId:o,readTargetProcessStartTime:fe}}function _e(e,t,n,r={}){if(r.signal?.aborted)throw x(`cancelled`,`abort-signal`);let i=l(`xcrun`,[`simctl`,`spawn`,e,t,`serve`,n,`--idle-timeout`,`60`,`--exit-on-disconnect`,`false`],{allowFailure:!0,captureOutput:!1,detached:!0}),a=i.child.pid??0;if(a<=0)throw x(`transport-failure`,`bridge-process-pid-missing`);let o=``;return i.child.stderr?.setEncoding(`utf8`),i.child.stderr?.on(`data`,e=>{o=be(o,String(e))}),{pid:a,wait:i.wait,isAlive:()=>i.child.exitCode===null&&i.child.signalCode===null,signal:e=>{u(a,e)||i.child.kill(e)},readLog:()=>o}}async function ve(e,t){if(t.signal?.aborted)throw x(`cancelled`,`abort-signal`);let n=Math.max(1,Math.floor(t.timeoutMs));return await new Promise((r,i)=>{let a=pe.createConnection({path:e}),o=!1,s=!1,c=setTimeout(()=>{p(x(`timeout`,`bridge-connect-timeout`)),a.destroy()},n),l=()=>{p(x(`cancelled`,`abort-signal`)),a.destroy()},u=()=>{o=!0,clearTimeout(c),t.signal?.removeEventListener(`abort`,l),a.off(`error`,d),a.off(`close`,f),a.setTimeout(0),r(a)},d=e=>{p(e),a.destroy()},f=()=>{o||p(x(`transport-failure`,`bridge-closed-before-connect`))},p=e=>{s||o||(s=!0,clearTimeout(c),t.signal?.removeEventListener(`abort`,l),a.off(`connect`,u),a.off(`error`,d),a.off(`close`,f),i(e))};a.once(`connect`,u),a.once(`error`,d),a.once(`close`,f),t.signal?.addEventListener(`abort`,l,{once:!0}),t.signal?.aborted&&l()})}async function ye(e,t){let n=o(),r=t.deadline,i=p({lockDirPath:e,owner:{pid:n,startTime:s(n),acquiredAtMs:Date.now()},timeoutMs:w(r,`cache-lock-deadline`),pollMs:100,ownerGraceMs:5e3,description:`iOS Simulator snapshot bridge cache`}),a=r.signal;if(!a)return await i;let c=!1,l,u=new Promise((e,t)=>{l=()=>{c=!0,t(x(`cancelled`,`abort-signal`))},a.addEventListener(`abort`,l,{once:!0}),a.aborted&&l()});try{return await Promise.race([i,u])}catch(e){throw c&&i.then(e=>e().catch(()=>void 0),()=>void 0),r.clock.isExpired()&&!(e instanceof b&&e.failureKind===`cancelled`)?x(`timeout`,`cache-lock-deadline`):e}finally{a.removeEventListener(`abort`,l)}}function be(e,t){let n=e+t;return n.length<=E?n:n.slice(n.length-E)}function xe(e,t,n){let r=_(`sha256`).update(t).digest(`hex`).slice(0,12),i=_(`sha256`).update(n).digest(`hex`).slice(0,12);return g.join(`/tmp`,`agent-device-ax-${r}-${e.processId()}-${i}`,`snapshot.sock`)}const D=new WeakSet;async function O(e,t){let n;try{n=(await t.wait).exitCode}catch{n=void 0}return D.has(t)||(D.add(t),e.emitDiagnostic({level:`error`,phase:`ios.snapshot-source.bridge-process-exit`,data:{pid:t.pid,...n===void 0?{}:{exitCode:n},stderr:Se(t.readLog())}})),x(`process-crash`,`bridge-exited`,{pid:t.pid,...n===void 0?{}:{exitCode:n}})}function Se(e){let t=y.from(e);return t.length<=65536?e:t.subarray(-65536).toString(`utf8`)}const k=`agent-device-simulator-ax-v1.6.0`;Object.freeze([`verb`,`requestId`,`pid`,`generation`,`snapshotTree`,`automationMode`,`maxDepth`,`maxNodes`,`maxDurationMs`,`maxResponseBytes`,`nativeLevelsHint`]),Object.freeze([`protocolVersion`,`sourceVersion`,`requestId`,`generation`,`ok`,`pid`,`tree`,`truncated`,`automationEnabled`,`recovery`,`error_kind`,`error_code`,`error`]),Object.freeze([`XC_kAXXCAttributeElementType`,`XC_kAXXCAttributeElementBaseType`,`XC_kAXXCAttributeLabel`,`XC_kAXXCAttributeValue`,`XC_kAXXCAttributeIdentifier`,`XC_kAXXCAttributeFrame`,`XC_kAXXCAttributeAutomationType`,`XC_kAXXCAttributeTraits`,`XC_kAXXCAttributeChildren`]);const A=[`requests`,`rejected`,`continuations`,`acceptedLevels`];function j(e){let t=e.recovery;if(!M(t))throw x(`malformed-tree`,`recovery-invalid`);let n=A.map(e=>[e,t[e]]);if(n.some(([,e])=>!Number.isSafeInteger(e)||e<0))throw x(`malformed-tree`,`recovery-invalid`);return Object.freeze(Object.fromEntries(n))}function Ce(e,t){let n;try{n=y.from(JSON.stringify(e),`utf8`)}catch(e){throw x(`malformed-tree`,`request-not-json`,{},e)}let r=n.length+4;if(r>t.maxRequestBytes)throw x(`transport-failure`,`request-limit-exceeded`,{frameBytes:r,maxRequestBytes:t.maxRequestBytes});let i=y.alloc(4);return i.writeUInt32BE(n.length,0),y.concat([i,n])}var we=class{header=y.alloc(4);headerBytes=0;chunks=[];payloadBytes=0;expectedBodyBytes;frame;maxFrameBytes;constructor(e){if(!Number.isSafeInteger(e)||e<=0)throw x(`malformed-tree`,`frame-limit-invalid`,{maxFrameBytes:e});this.maxFrameBytes=e}push(e){if(this.frame)return this.acceptTrailingChunk(e);let t=this.readHeader(e);if(t&&(this.appendPayload(e,t.offset,t.bodyBytes),this.payloadBytes===t.bodyBytes))return this.frame=y.concat(this.chunks,t.bodyBytes),this.frame}acceptTrailingChunk(e){if(e.length>0)throw x(`malformed-tree`,`multiple-frames`,{trailingBytes:e.length});return this.frame}readHeader(e){if(this.headerBytes===4)return{offset:0,bodyBytes:this.expectedBodyBytes};let t=Math.min(4-this.headerBytes,e.length);if(e.copy(this.header,this.headerBytes,0,t),this.headerBytes+=t,this.headerBytes<4)return;let n=this.header.readUInt32BE(0);if(n===0||n>this.maxFrameBytes)throw x(`malformed-tree`,`frame-limit-exceeded`,{bodyBytes:n,maxFrameBytes:this.maxFrameBytes});return this.expectedBodyBytes=n,{offset:t,bodyBytes:n}}appendPayload(e,t,n){let r=n-this.payloadBytes,i=e.length-t;if(i>r)throw x(`malformed-tree`,`multiple-frames`,{trailingBytes:i-r});i!==0&&(this.chunks.push(e.subarray(t)),this.payloadBytes+=i)}finish(){if(this.frame)return this.frame;throw x(`transport-failure`,`bridge-frame-incomplete`,{headerBytes:this.headerBytes,payloadBytes:this.payloadBytes,expectedBodyBytes:this.expectedBodyBytes})}};function Te(e){let t;try{t=JSON.parse(e.toString(`utf8`))}catch(e){throw x(`malformed-tree`,`response-not-json`,{},e)}if(!M(t))throw x(`malformed-tree`,`response-not-object`);return t}function Ee(e){return Object.freeze({verb:`describe`,requestId:e.requestId,pid:e.pid,generation:e.generation,snapshotTree:!0,automationMode:!0,maxDepth:e.maxDepth,maxNodes:e.maxNodes,maxDurationMs:e.maxDurationMs,maxResponseBytes:e.maxResponseBytes,...e.nativeLevelsHint===void 0?{}:{nativeLevelsHint:e.nativeLevelsHint}})}function De(e,t){if(e.protocolVersion!==1)throw x(`transport-failure`,`protocol-version-mismatch`,{expected:1,observed:e.protocolVersion});if(e.sourceVersion!==`agent-device-simulator-ax-v1.6.0`)throw x(`transport-failure`,`source-version-mismatch`,{expected:k,observed:e.sourceVersion});if(e.requestId!==t)throw x(`transport-failure`,`request-id-mismatch`,{expected:t,observed:e.requestId})}function Oe(e,t){if(typeof e.pid!=`number`||e.pid!==t.pid)throw x(`stale-target`,`bridge-pid-mismatch`,{expectedPid:t.pid,observedPid:e.pid});if(e.generation!==t.generation)throw x(`stale-target`,`bridge-generation-mismatch`,{expectedGeneration:t.generation,observedGeneration:e.generation})}function ke(e){let t=e.error_kind,n=typeof e.error_code==`string`?e.error_code:`guest-error`,r=typeof e.error==`string`?e.error:void 0,i=r?{guestMessage:r.slice(0,1024)}:{};throw x(t===`unsupported`?`unsupported`:t===`malformed_tree`?`malformed-tree`:t===`application_not_responding`?`timeout`:t===`application_unavailable`?`transport-failure`:t===`bad_request`?`malformed-tree`:`transport-failure`,n,i)}function M(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function Ae(e){let t=new we(e.limits.maxResponseBytes-4),n=w(e.deadline,`bridge-request-deadline`);return await new Promise((r,i)=>{let a=!1,o=!1,s=setTimeout(()=>{p(x(`timeout`,`bridge-request-deadline`,{dispatched:o})),e.socket.destroy()},n),c=()=>{p(x(`cancelled`,`abort-signal`,{dispatched:o})),e.socket.destroy()},l=n=>{try{if(!Buffer.isBuffer(n))throw x(`transport-failure`,`bridge-data-invalid`);let r=t.push(n);if(r){let t=Te(r);if(De(t,e.requestId),Oe(t,{pid:e.expectedPid,generation:e.expectedGeneration}),t.ok!==!0&&ke(t),typeof t.truncated!=`boolean`)throw x(`malformed-tree`,`truncated-invalid`);f(t);return}}catch(t){p(t),e.socket.destroy()}},u=e=>p(S(e)),d=()=>{a||(e.process.isAlive()?p(x(`transport-failure`,`bridge-connection-closed`)):O(e.host,e.process).then(p))};e.process.wait.then(()=>{a||O(e.host,e.process).then(p)},e=>{a||p(S(e))});let f=e=>m(()=>r(e)),p=e=>m(()=>i(e)),m=t=>{a||(a=!0,clearTimeout(s),e.deadline.signal?.removeEventListener(`abort`,c),e.socket.off(`data`,l),e.socket.off(`error`,u),e.socket.off(`close`,d),t())};e.socket.on(`data`,l),e.socket.on(`error`,u),e.socket.on(`close`,d),e.deadline.signal?.addEventListener(`abort`,c,{once:!0});try{if(e.deadline.signal?.aborted)throw x(`cancelled`,`abort-signal`);o=!0,e.socket.write(e.frame)}catch(t){p(S(t)),e.socket.destroy()}})}var je=class{sessions=new Map;requestQueues=new Map;ownerId=v();closed=!1;host;constructor(e){this.host=e}async request(e){if(this.closed)throw x(`unsupported`,`source-closed`);return await this.withSimulatorLock(e.target.udid,e.deadline,()=>this.requestInSimulator(e))}async requestInSimulator(e){if(this.closed)throw x(`unsupported`,`source-closed`);let t=e.deadline;w(t,`bridge-request-deadline`);let n=this.sessions.get(e.target.udid),r=await this.ensureSession(e,t);try{let n=await this.readTargetStartTime(e.target,t),i=await this.exchange(r,e,t);return await this.assertTargetStillCurrent(e.target,n,t),i}catch(e){throw await this.handleRequestFailure(e,r,n)}}async handleRequestFailure(e,t,n){let r=S(e);return Ne(r,t,n)?await this.removeSession(t,!0):r.failureKind===`process-crash`?await this.removeSession(t,!1):r.failureKind===`transport-failure`&&(t.socket?.destroy(),t.socket=void 0),r}async withSimulatorLock(e,t,n){let r=this.requestQueues.get(e)??Promise.resolve(),i,a=new Promise(e=>{i=e}),o=r.then(()=>a);this.requestQueues.set(e,o);try{return await Me(r,t),await n()}finally{i(),this.requestQueues.get(e)===o&&this.requestQueues.delete(e)}}async close(){if(this.closed)return;this.closed=!0;let e=[...this.sessions.values()];this.sessions.clear(),await Promise.all(e.map(async e=>await this.dispose(e,!0)))}async ensureSession(e,t){let n=e.target.udid,r=this.sessions.get(n);if(r&&r.bridgePath===e.bridge.path&&r.process.isAlive())return(!r.socket||r.socket.destroyed)&&(r.socket=await this.connectUntilReady(r,t)),r;r&&await this.removeSession(r,!0);let i=xe(this.host,e.target.udid,this.ownerId);await this.host.ensureDirectory(g.dirname(i)),await this.host.remove(i);let a=this.host.start(e.target.udid,e.bridge.path,i,{signal:t.signal}),o={udid:e.target.udid,bridgePath:e.bridge.path,socketPath:i,process:a};this.sessions.set(n,o);try{return o.socket=await this.connectUntilReady(o,t),o}catch(e){throw await this.removeSession(o,!0),S(e)}}async connectUntilReady(e,t){let n;for(;;){let r=w(t,`bridge-connect-deadline`);if(!e.process.isAlive())throw await O(this.host,e.process);try{return await this.host.connect(e.socketPath,{signal:t.signal,timeoutMs:Math.min(250,r)})}catch(e){if(n=e,e instanceof b&&e.failureKind===`cancelled`)throw e;let r=Math.min(20,w(t,`bridge-connect-deadline`));try{await T(t,r,`bridge-connect-deadline`)}catch(e){throw S(e)}}if(n instanceof b&&n.failureKind===`timeout`)throw n}}async exchange(e,t,n){(!e.socket||e.socket.destroyed)&&(e.socket=await this.connectUntilReady(e,n));let r=v(),i=Ce(Ee({requestId:r,pid:t.target.pid,generation:t.target.generation,maxDepth:Math.min(t.limits.maxTraversalDepth,t.maxDepth),maxNodes:t.limits.maxNodes,maxDurationMs:w(n,`bridge-request-deadline`),maxResponseBytes:t.limits.maxResponseBytes,...t.nativeLevelsHint===void 0?{}:{nativeLevelsHint:t.nativeLevelsHint}}),t.limits);return await Ae({process:e.process,socket:e.socket,frame:i,requestId:r,deadline:n,limits:t.limits,expectedPid:t.target.pid,expectedGeneration:t.target.generation,host:this.host})}async readTargetStartTime(e,t){let n=await this.host.readTargetProcessStartTime(e.pid,{signal:t.signal,timeoutMs:w(t,`target-identity-deadline`)});if(!n)throw x(`stale-target`,`target-process-unavailable`,{pid:e.pid,generation:e.generation});if(e.processStartTime!==void 0&&e.processStartTime!==n)throw x(`stale-target`,`target-process-changed`,{pid:e.pid,generation:e.generation,expectedStartTime:e.processStartTime,observedStartTime:n});return n}async assertTargetStillCurrent(e,t,n){let r=await this.host.readTargetProcessStartTime(e.pid,{signal:n.signal,timeoutMs:w(n,`target-identity-deadline`)});if(r!==t)throw x(`stale-target`,`target-process-changed`,{pid:e.pid,generation:e.generation,expectedStartTime:t,observedStartTime:r})}async removeSession(e,t){this.sessions.get(e.udid)===e&&this.sessions.delete(e.udid),await this.dispose(e,t)}async dispose(e,t){e.socket?.destroy(),e.socket=void 0,t&&e.process.isAlive()&&(e.process.signal(`SIGTERM`),await N(e.process,500),e.process.isAlive()&&(e.process.signal(`SIGKILL`),await N(e.process,500))),await this.host.remove(e.socketPath)}};async function Me(e,t){let n=w(t,`bridge-request-deadline`);await Promise.race([e,T(t,n,`bridge-request-deadline`).then(()=>{throw x(`timeout`,`bridge-request-deadline`)})])}function Ne(e,t,n){return(e.failureKind===`cancelled`||e.failureKind===`timeout`)&&(e.details?.dispatched===!0||n!==t)}async function N(e,t){await Promise.race([e.wait.catch(()=>void 0),new Promise(e=>setTimeout(e,t))])}const P=16777216,F=12e4,I=1e4,Pe=Object.freeze({maxRequestBytes:65536,maxResponseBytes:4194304,maxNodes:5e3,maxTraversalDepth:64,maxDurationMs:5e3});function L(t){let n={...Pe,...t??{}};for(let[t,r]of Object.entries(n))if(!Number.isSafeInteger(r)||r<=0)throw new e(`INVALID_ARGS`,`Snapshot source limit ${t} must be a positive integer`,{name:t,value:r});if(n.maxRequestBytes>n.maxResponseBytes)throw new e(`INVALID_ARGS`,`Snapshot source request bytes cannot exceed response bytes`,{maxRequestBytes:n.maxRequestBytes,maxResponseBytes:n.maxResponseBytes});if(n.maxRequestBytes>P||n.maxResponseBytes>P)throw new e(`INVALID_ARGS`,`Snapshot source frame limits exceed the bridge bound`,{maxRequestBytes:n.maxRequestBytes,maxResponseBytes:n.maxResponseBytes,maximumFrameBytes:P});if(n.maxNodes>I||n.maxTraversalDepth>128)throw new e(`INVALID_ARGS`,`Snapshot source tree limits exceed the bridge bound`,{maxNodes:n.maxNodes,maxTraversalDepth:n.maxTraversalDepth,maximumNodes:I,maximumDepth:128});if(n.maxDurationMs>F)throw new e(`INVALID_ARGS`,`Snapshot source duration exceeds the bridge bound`,{maxDurationMs:n.maxDurationMs,maximumDurationMs:F});if(n.maxRequestBytes<=4||n.maxResponseBytes<=4)throw new e(`INVALID_ARGS`,`Snapshot source frame limits must leave room for a body`,{maxRequestBytes:n.maxRequestBytes,maxResponseBytes:n.maxResponseBytes});return Object.freeze(n)}const R=[`SnapshotBridge.m`,`SnapshotBridgeRuntime.m`,`SnapshotBridgeRuntime.h`,`SnapshotBridgeCapture.h`,`SnapshotBridgeCapture.m`],Fe=[`SnapshotBridge.m`,`SnapshotBridgeRuntime.m`,`SnapshotBridgeCapture.m`];async function Ie(e,t,n){let r=_(`sha256`);for(let i of R){let a=g.join(t,i);if(w(n,`native-source-fingerprint-deadline`),!e.exists(a))throw x(`unsupported`,`native-source-missing`,{filePath:a});r.update(i),r.update(`\0`),r.update(await e.readBinary(a)),r.update(`\0`)}return r.digest(`hex`)}async function Le(e,t,n){let r=await z(e,`xcodebuild`,[`-version`],n),i=await z(e,`sw_vers`,[`-productVersion`],n),a=await z(e,`sw_vers`,[`-buildVersion`],n),o=await z(e,`uname`,[`-m`],n),s=await z(e,`xcrun`,[`--sdk`,`iphonesimulator`,`--show-sdk-version`],n),c=t.trim();if(!c)throw x(`unsupported`,`simulator-runtime-missing`);if(o!==`arm64`&&o!==`x86_64`)throw x(`unsupported`,`simulator-architecture-unsupported`,{architecture:o});return{xcode:r,macosProductVersion:i,macosBuild:a,architecture:o,simulatorSdk:s,simulatorRuntime:c}}async function z(e,t,n,r){let i=await Re(e,t,n,r);if(i.exitCode!==0)throw x(`unsupported`,`toolchain-probe-failed`,{command:t,exitCode:i.exitCode,stderr:i.stderr.slice(0,1024)});let a=(i.stdout||i.stderr).trim();if(!a)throw x(`unsupported`,`toolchain-probe-empty`,{command:t});return a}async function Re(e,t,n,r){try{return await B(e,t,n,r)}catch(i){if(!d(i))throw i;if(r.signal?.aborted)throw x(`cancelled`,`abort-signal`);if(r.clock.remainingMs(r.now())<=0)throw i;return await B(e,t,n,r)}}function B(e,t,n,r){return e.run(t,n,{allowFailure:!0,signal:r.signal,timeoutMs:Math.min(h,w(r,`toolchain-probe-deadline`))})}const V=`snapshot-bridge`,H=`manifest.json`,U=12e4;async function ze(e){let t=e.deadline,n=e.sourceRoot??Be(e.host),r=await Ie(e.host,n,t),i=await Le(e.host,e.runtime,t),a=He({schemaVersion:1,protocolVersion:1,sourceVersion:k,sourceHash:r,toolchain:i}),o=e.cacheRoot??g.join(e.host.homeDirectory(),`.agent-device`,`snapshot-source`),s=g.join(o,a);return await f({acquire:()=>e.host.acquireLock(g.join(o,`${a}.lock`),{deadline:t}),task:async()=>{let c=await Ve(e.host,s,{sourceHash:r,cacheKey:a,toolchain:i},t);if(c)return c;w(t,`native-build-deadline`),e.host.exists(s)&&await e.host.remove(s),w(t,`native-build-deadline`),await e.host.ensureDirectory(o);let l=g.join(o,`.${a}.${e.host.processId()}.tmp`);w(t,`native-build-deadline`),await e.host.remove(l);try{w(t,`native-build-deadline`),await e.host.ensureDirectory(l);let o=g.join(l,V),c=await e.host.run(`xcrun`,[`--sdk`,`iphonesimulator`,`clang`,`-arch`,i.architecture,`-mios-simulator-version-min=15.0`,`-fobjc-arc`,`-Werror`,`-Wall`,`-Wextra`,`-framework`,`Foundation`,`-framework`,`CoreGraphics`,...Fe.map(e=>g.join(n,e)),`-o`,o],{signal:t.signal,timeoutMs:Math.min(U,w(t,`native-build-deadline`)),allowFailure:!0});if(c.exitCode!==0||!e.host.exists(o))throw x(`unsupported`,`native-build-failed`,{exitCode:c.exitCode,stderr:c.stderr.slice(0,4096)});w(t,`native-build-deadline`),await e.host.chmod(o,493);let u=await W(e.host,o,t),d={schemaVersion:1,protocolVersion:1,sourceVersion:k,sourceHash:r,cacheKey:a,toolchain:i,binarySha256:u};return await e.host.writeText(g.join(l,H),`${JSON.stringify(d,null,2)}\n`),w(t,`native-build-deadline`),await e.host.rename(l,s),{path:g.join(s,V),sourceHash:r,cacheKey:a,protocolVersion:1,sourceVersion:k}}catch(t){throw await e.host.remove(l),t}}})}function Be(e){let t=e.projectRoot(),n=g.join(t,`apple`,`snapshot-bridge`);if(R.every(t=>e.exists(g.join(n,t))))return n;let r=g.join(t,`dist`,`apple`,`snapshot-bridge`);if(R.every(t=>e.exists(g.join(r,t))))return r;throw x(`unsupported`,`native-source-missing`,{projectRoot:t})}async function Ve(e,t,n,r){let i=g.join(t,V);if(!(!e.exists(i)||!e.exists(g.join(t,H))))try{let a=JSON.parse(await e.readText(g.join(t,H)));return a.schemaVersion!==1||a.protocolVersion!==1||a.sourceVersion!==`agent-device-simulator-ax-v1.6.0`||a.sourceHash!==n.sourceHash||a.cacheKey!==n.cacheKey||JSON.stringify(a.toolchain)!==JSON.stringify(n.toolchain)||typeof a.binarySha256!=`string`||await W(e,i,r)!==a.binarySha256?void 0:{path:i,sourceHash:n.sourceHash,cacheKey:n.cacheKey,protocolVersion:1,sourceVersion:k}}catch(e){if(e instanceof b&&(e.failureKind===`cancelled`||e.failureKind===`timeout`))throw e;return}}async function W(e,t,n){return w(n,`native-cache-hash-deadline`),_(`sha256`).update(await e.readBinary(t)).digest(`hex`)}function He(e){return _(`sha256`).update(JSON.stringify(e)).digest(`hex`).slice(0,32)}const Ue=h+U;function We(e){let t=e.now??Date.now,n=new Map,r=ue({waitMs:2e3,waitGrant:`first-caller`,retryAfterMs:6e4,now:t}),i=async(r,i)=>{let a=C(Ue,i,t);try{let t=await e.host.withDiagnosticTimer(`ios.snapshot-source.prepare`,async()=>await ze({host:e.host,runtime:r,limits:e.limits,deadline:a,sourceRoot:e.sourceRoot,cacheRoot:e.cacheRoot}),{producer:e.producer});return n.set(r,t),t}catch(e){throw S(e)}};return{readyBinary:async(e,t,a)=>n.get(e)||await r.value(e,{start:t=>i(e,t),wait:(e,n)=>T(t,e,a,n),pending:()=>x(`preparing`,`bridge-preparation-pending`)}),close:()=>{n.clear(),r.close()}}}const G=Object.freeze({elementType:`XC_kAXXCAttributeElementType`,elementBaseType:`XC_kAXXCAttributeElementBaseType`,label:`XC_kAXXCAttributeLabel`,value:`XC_kAXXCAttributeValue`,identifier:`XC_kAXXCAttributeIdentifier`,frame:`XC_kAXXCAttributeFrame`,automationType:`XC_kAXXCAttributeAutomationType`,traits:`XC_kAXXCAttributeTraits`,children:`XC_kAXXCAttributeChildren`}),K=`Other.Other.Application.Group.Window.Sheet.Drawer.Alert.Dialog.Button.RadioButton.RadioGroup.CheckBox.DisclosureTriangle.PopUpButton.ComboBox.MenuButton.ToolbarButton.Popover.Keyboard.Key.NavigationBar.TabBar.TabGroup.Toolbar.StatusBar.Table.TableRow.TableColumn.Outline.OutlineRow.Browser.CollectionView.Slider.PageIndicator.ProgressIndicator.ActivityIndicator.SegmentedControl.Picker.PickerWheel.Switch.Toggle.Link.Image.Icon.SearchField.ScrollView.ScrollBar.StaticText.TextField.SecureTextField.DatePicker.TextView.Menu.MenuItem.MenuBar.MenuBarItem.Map.WebView.IncrementArrow.DecrementArrow.Timeline.RatingIndicator.ValueIndicator.SplitGroup.Splitter.RelevanceIndicator.ColorWell.HelpTag.Matte.DockItem.Ruler.RulerMarker.Grid.LevelIndicator.Cell.LayoutArea.LayoutItem.Handle.Stepper.Tab.TouchBar.StatusItem`.split(`.`),q={UIApplication:`Application`,UIWindow:`Window`},Ge=new Set(Object.values(G)),Ke=1n<<8n;function qe(e,t,n){let r=Array.isArray(e)?e:[e];if(r.length===0||r.some(e=>!M(e)))throw x(`malformed-tree`,`guest-tree-root-invalid`);let i=[],a=[],o=0;for(let e of r)c(e,void 0,0,!1);if(i.length>n.maxNodes)throw x(`malformed-tree`,`node-limit-exceeded`,{nodeCount:i.length,maxNodes:n.maxNodes});if(o>n.maxTraversalDepth)throw x(`malformed-tree`,`traversal-depth-exceeded`,{maxTraversalDepth:o,maxAllowedDepth:n.maxTraversalDepth});if(typeof t.truncated!=`boolean`)throw x(`malformed-tree`,`truncated-invalid`);let s=Qe(i.find(e=>e.type===`Application`||e.type===`Window`));return{nodes:i,maxTraversalDepth:o,viewport:s,opaqueRemoteElements:a.filter(e=>Xe(e,s)).length};function c(e,t,r,s){if(i.length>=n.maxNodes)throw x(`malformed-tree`,`node-limit-exceeded`,{maxNodes:n.maxNodes});for(let t of Object.keys(e))if(!Ge.has(t))throw x(`malformed-tree`,`node-contains-unknown-field`,{key:t});let l=e[G.children];if(!Array.isArray(l))throw x(`malformed-tree`,`children-invalid`);let u=i.length,d=Je(e,u,t,r);i.push(d),o=Math.max(o,r),Ye(d,l.length,s)&&a.push(d.rect);let f=s||d.type===`WebView`;for(let e of l){if(!M(e))throw x(`malformed-tree`,`child-invalid`);c(e,u,r+1,f)}}}function Je(e,t,n,r){let i=Y(e[G.elementType]),a=Y(e[G.elementBaseType]),o=Z(e[G.automationType]),s=Ze(e[G.frame]),c=$e(e[G.traits]);return{index:t,...n===void 0?{}:{parentIndex:n},...J(i,o)?{type:J(i,o)}:{},...i?{role:i}:{},...a&&a!==i?{subrole:a}:{},...Y(e[G.label])?{label:Y(e[G.label])}:{},...X(e[G.value])?{value:X(e[G.value])}:{},...Y(e[G.identifier])?{identifier:Y(e[G.identifier])}:{},...s?{rect:s}:{},...c===void 0?{}:{enabled:c},depth:r}}function J(e,t){if(e!==void 0&&q[e])return q[e];if(e!==void 0&&K.includes(e))return e;if(t!==void 0)return K[t]??`Other`}function Ye(e,t,n){return n&&e.role===`AXRemoteElement`&&t===0}function Xe(e,t){return e===void 0?!0:r(e)?t.kind!==`reported`||n(e,t.rect):!1}function Ze(e){if(e===void 0)return;if(!M(e))throw x(`malformed-tree`,`frame-invalid`);let t=[`X`,`Y`,`Width`,`Height`].map(t=>e[t]);if(!t.every(e=>typeof e==`number`&&Number.isFinite(e)))throw x(`malformed-tree`,`frame-invalid`);let[n,r,i,a]=t;if(i<0||a<0)throw x(`malformed-tree`,`frame-invalid`);return{x:n,y:r,width:i,height:a}}function Qe(e){return!e||e.type!==`Application`&&e.type!==`Window`?{kind:`missing`,reason:`not-provided`}:r(e.rect)?{kind:`reported`,rect:e.rect}:{kind:`missing`,reason:e.rect?`invalid`:`not-provided`}}function Y(e){return typeof e==`string`&&e.length>0?e:void 0}function X(e){if(typeof e==`string`)return e.length>0?e:void 0;if(typeof e==`number`||typeof e==`boolean`)return String(e);if(e!=null)throw x(`malformed-tree`,`scalar-invalid`)}function $e(e){if(e!=null){if(typeof e!=`string`||!/^\d{1,20}$/.test(e))throw x(`malformed-tree`,`traits-invalid`);return(BigInt(e)&Ke)===0n}}function Z(e){if(e!=null){if(!Number.isSafeInteger(e))throw x(`malformed-tree`,`automation-type-invalid`);return e}}const Q=`simulator-ax-bridge`;function et(e={}){let t=e.host??ge(),n=new je(t),r=new he,i=We({host:t,limits:L(e.limits),producer:Q,sourceRoot:e.sourceRoot,cacheRoot:e.cacheRoot}),a=!1;return{acquire:async o=>{try{if(a)throw x(`unsupported`,`source-closed`);tt(o);let s=L({...e.limits,...o.limits}),c=C(s.maxDurationMs,o.signal),l=rt(o.hint,s.maxTraversalDepth),u=l+1,d=o.hint.rawTraversalDepth!==null;return await t.withDiagnosticTimer(`ios.snapshot-source.acquire`,async()=>{let e=await i.readyBinary(o.target.runtime,c,`bridge-preparation-deadline`),a=r.consume(o.target,u,d),f=await n.request({target:o.target,bridge:e,limits:s,maxDepth:l,nativeLevelsHint:a.nativeLevels,deadline:c});w(c,`snapshot-decode-deadline`);let p=it(o.hint,o.target,f,s);return nt(t,r,o.target,u,d,a,f),{stage:`acquired`,acquisition:p}},{producer:Q})}catch(e){let t=S(e);return{stage:`failed`,failure:{kind:t.failureKind,code:t.failureCode,...t.details?{details:t.details}:{}}}}},close:async()=>{a||(a=!0,i.close(),await n.close())}}}function tt(t){if(!t.target.udid.trim()||!t.target.runtime.trim()||!t.target.generation.trim()||!Number.isSafeInteger(t.target.pid)||t.target.pid<=0)throw new e(`INVALID_ARGS`,`Simulator snapshot source target identity is incomplete`);let n=t.hint;if(n.projection!==`raw`&&n.projection!==`regular`||![`full`,`surface-observation`].includes(n.acquisitionIntent)||typeof n.interactiveOnly!=`boolean`||typeof n.customActions!=`boolean`||!$(n.rawTraversalDepth)||!$(n.regularPresentedDepth))throw new e(`INVALID_ARGS`,`Simulator snapshot source capture hint is invalid`)}function nt(e,t,n,r,i,a,o){let s=j(o),c=o.truncated===!0,l=t.learn(n,r,i,s);e.emitDiagnostic({level:`debug`,phase:`ios_snapshot_source_recovery`,data:{producer:Q,...n.targetId?{targetId:n.targetId}:{},generation:n.generation,requestedLevels:r,hint:a.reason,...a.nativeLevels===void 0?{}:{hintedLevels:a.nativeLevels},...s,truncated:c,learning:l}})}function rt(t,n){let r=t.rawTraversalDepth??n;if(r>n)throw new e(`INVALID_ARGS`,`Simulator snapshot source depth exceeds its bound`,{requested:r,maximum:n});return r}function $(e){return e===null||Number.isSafeInteger(e)&&e>=0}function it(e,t,n,r){if(n.automationEnabled!==!0)throw x(`unsupported`,`automation-mode-unavailable`);let i=n.tree,a=n.truncated;if(typeof a!=`boolean`)throw x(`malformed-tree`,`truncated-invalid`);let o=qe(i,{truncated:a},r),s=n.generation;if(typeof s!=`string`||!s)throw x(`malformed-tree`,`generation-invalid`);if(o.opaqueRemoteElements>0)throw x(`unsupported`,`remote-content-boundary`,{remoteElements:o.opaqueRemoteElements});let c=Object.freeze(o.nodes.map(e=>Object.freeze({...e,pid:t.pid}))),l=at(e,a,o.viewport),u=Object.freeze({...t.targetId?{targetId:t.targetId}:{},generation:s}),d={producer:Q,nodes:c,truncated:a,viewport:o.viewport,lineage:u,residue:l};return e.acquisitionIntent===`full`?{...d,intent:`full`,hint:{...e,acquisitionIntent:`full`}}:{...d,intent:`surface-observation`,hint:{...e,acquisitionIntent:`surface-observation`}}}function at(e,t,n){return Object.freeze([{kind:`unavailable-fact`,fact:`hittability`},...e.interactiveOnly?[{kind:`unavailable-fact`,fact:`interactive-query`}]:[],...t?[{kind:`truncated`}]:[],...n.kind===`missing`?[{kind:`missing-viewport`,reason:n.reason}]:[]])}export{et as createSimulatorSnapshotSource};
|
package/dist/src/adb-executor.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{C as e}from"./sdk-contracts.js";import{a as t,r as n}from"./adb-
|
|
2
|
-
`).map(e=>e.trim().split(/\s+/)).filter(e=>e.length>=3).map(([,e,t])=>{let r=e;return{local:r,remote:t,ownerId:n.get(r)}})}function
|
|
1
|
+
import{C as e}from"./sdk-contracts.js";import{a as t,d as n,f as r,i,l as a,m as o,n as s,p as c,s as l,u}from"./adb-transport.js";import{c as d,n as f}from"./adb-failure.js";import p from"node:path";import{AsyncLocalStorage as m}from"node:async_hooks";let h;const g=new m;function _(e){h=e}function v(){if(!h)throw Error(`Android adb host port is not bound; import the platform composition wiring (src/platform-runtime-android-adb-host.ts) before using the adb/IME cluster.`);return h}async function y(e,t){let n=v(),r=g.getStore(),i=n.coerceAdbResult(r?await r(e,t):await n.execAdb(e,{...t,allowFailure:!0}));if(!t?.allowFailure&&i.exitCode!==0){let{androidAdbResultError:t}=await import(`./adb-failure.js`).then(e=>e.t),{serializeAndroidAdbInvocation:n}=await import(`./adb-transport.js`).then(e=>e.t);throw t(`adb ${n(e).join(` `)} exited with code ${i.exitCode}`,i)}return i}async function b(e,t){return await g.run(e,t)}function x(e){v().emitDiagnostic(e)}const S=new WeakSet;function C(e){return w(typeof e==`function`?{exec:e}:e)}function w(e){if(S.has(e))return e;let t={...e,exec:d(T(e.exec)),...e.pull?{pull:d(T(e.pull))}:{},...e.install?{install:d(T(e.install))}:{},...e.installBundle?{installBundle:d(e.installBundle)}:{}};return S.add(t),t}function T(e){return async(...t)=>v().coerceAdbResult(await e(...t))}const E=new WeakSet;function D(t){let n=C(t);if(n.reverse&&E.has(n.reverse))return n.reverse;let r=n.reverse??O(n.exec),i=new Map,a={async ensure(t,n){let a=i.get(t.local);if(a&&a.ownerId!==t.ownerId)throw new e(`COMMAND_FAILED`,`Android port reverse ${t.local} is already owned by ${a.ownerId??`another session`}`,{current:a,requested:t});a?.remote!==t.remote&&(await r.ensure(t,n),i.set(t.local,{...t}))},async remove(e,t){if(!i.has(e)){await r.remove(e,t);return}await r.remove(e,t),i.delete(e)},async removeAllOwned(e,t){let n=[...i.values()].filter(t=>t.ownerId===e).map(e=>e.local);if(n.length===0){await r.removeAllOwned(e,t);return}for(let e of n)await r.remove(e,t),i.delete(e)},async list(e){return r.list?await r.list(e):[...i.values()]}};return E.add(a),a}function O(e){let t=new Map;return{async ensure(n,r){if(await e([`reverse`,n.local,n.remote],{allowFailure:!1,signal:r?.signal,timeoutMs:r?.timeoutMs}),n.ownerId){let e=t.get(n.ownerId)??new Set;e.add(n.local),t.set(n.ownerId,e)}},async remove(n,r){let i=await e([`reverse`,`--remove`,n],{allowFailure:!0,signal:r?.signal,timeoutMs:r?.timeoutMs});if(i.exitCode!==0&&!A(i.stdout,i.stderr))throw f(`Failed to remove Android port reverse ${n}`,i,{local:n});for(let e of t.values())e.delete(n)},async removeAllOwned(e,n){let r=[...t.get(e)??[]];for(let e of r)await this.remove(e,n);t.delete(e)},async list(n){let r=await e([`reverse`,`--list`],{allowFailure:!0,signal:n?.signal,timeoutMs:n?.timeoutMs});return r.exitCode===0?k(r.stdout,t):[]}}}function k(e,t){let n=new Map;for(let[e,r]of t)for(let t of r)n.set(t,e);return e.split(`
|
|
2
|
+
`).map(e=>e.trim().split(/\s+/)).filter(e=>e.length>=3).map(([,e,t])=>{let r=e;return{local:r,remote:t,ownerId:n.get(r)}})}function A(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`listener`)&&n.includes(`not found`)}const j=new m;function M(e,t={}){return N(e.id,t.serverPort)}function N(e,t){return d(async(n,r)=>{let i=F(e,t,n,r);return await v().withoutAdbCommandExecutorOverride(async()=>await v().execAdb(i.invocation,i.options))})}function P(e,t){return(n,r)=>{let i=F(e,t,n,r);return v().spawnAdb(i.invocation,i.options)}}function F(e,t,n,r){let{serverPort:i,...a}=r??{};return{invocation:I(e,n,L(e,t,i)),options:a}}function I(e,t,n){let a=u(t),o=s(a.target,e);if(n===void 0)return i(o,a.command,[`-s`,e,...t]);let c=l(a,{port:n});return i(r(c.target,e),c.command)}function L(e,t,n){let r=j.getStore();return r&&X(r,{kind:`serial`,serial:e}),r?.serverPort===void 0?t??n:(c(t,r.serverPort),c(n,r.serverPort))}function R(e,t={}){let n=M(e,t);return{exec:n,spawn:P(e.id,t.serverPort),reverse:O(n),pull:async(e,t,r)=>await n([`pull`,e,t],r),install:async(e,t)=>{let{installArgs:r,execOptions:i}=a(t);return await n([`install`,...r,e],i)}}}function z(e,t){let n=Y(e);return t||(n?.serial===e.id?n.provider.exec:M(e))}function B(e,t){let n=Y(e);return t?C(t):n?.serial===e.id?C(n.provider):R(e)}function V(e){let t=Y(e);return t?.serial===e.id?{mode:`transport-composed`,...t.provider.spawn?{spawn:t.provider.spawn}:{}}:{mode:`local`}}function H(e){let t=Y(e);return t?.serial===e.id?t.provider.text:void 0}function U(e){let t=Y(e);return t?.serial===e.id&&t.provider.touch?t.provider:void 0}function W(e,t){if(t)return C(t);if(e)return B(e);let n=j.getStore();if(n)return C(n.provider)}async function G(e,t,n){if(!e)return await n();let r={provider:C(e),serial:t.serial,...t.serverPort===void 0?{}:{serverPort:t.serverPort}},i=K(r),a=async()=>await j.run(r,async()=>await v().withAdbCommandExecutorOverride(i,n));return t.serverPort===void 0?await a():await b(q(r,t.serverPort),a)}function K(e){return(r,i,a)=>{if(!Z(r)||e.serverPort===void 0&&r!==`adb`)return;let o=u(i);if(X(e,o.target.selector),o.target.selector.kind===`serial`){if(o.target.selector.serial!==e.serial)return;e.serverPort!==void 0&&n(o.target,e.serverPort);let r=t(i,e.serial);return r===void 0?void 0:v().withoutAdbCommandExecutorOverride(async()=>await e.provider.exec(r,a))}let s=e.serverPort;if(s!==void 0)return J(e,s,o,a)}}function q(e,t){return async(n,r)=>(X(e,n.target.selector),J(e,t,n,r))}async function J(e,t,n,a){c(t,a?.serverPort);let{serverPort:o,...s}=a??{},u=r(n.target,e.serial),d=l(i(u,n.command),{port:t}),f=v();return await f.withoutAdbCommandExecutorOverride(async()=>await f.execAdb(d,{...s,allowFailure:!0}))}function Y(e){let t=j.getStore();return t&&X(t,{kind:`serial`,serial:e.id}),t}function X(e,t){e?.serverPort!==void 0&&o(t,e.serial)}function Z(e){return p.basename(e).replace(/\.(?:com|exe|bat|cmd)$/i,``)===`adb`}async function Q(t,n,r){let{device:i,provider:a,...o}=r??{},s=W(i,a),c=s?.pull,l=v();if(c)return await l.withoutAdbCommandExecutorOverride(async()=>await c(t,n,o));let u=s?.exec;if(!u)throw new e(`COMMAND_FAILED`,`Android adb pull requires an adb provider`);return await l.withoutAdbCommandExecutorOverride(async()=>await u([`pull`,t,n],o))}async function $(t,n){let{device:r,provider:i,...o}=n??{},s=W(r,i),c=s?.install,l=v();if(c)return await l.withoutAdbCommandExecutorOverride(async()=>await c(t,o));let u=s?.exec;if(!u)throw new e(`COMMAND_FAILED`,`Android adb install requires an adb provider`);let{installArgs:d,execOptions:f}=a(o);return await l.withoutAdbCommandExecutorOverride(async()=>await u([`install`,...d,t],f))}export{z as a,U as c,D as d,_ as f,b as g,y as h,R as i,V as l,v as m,Q as n,B as o,x as p,M as r,H as s,$ as t,G as u};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{C as t}from"./sdk-contracts.js";var n=e({ADB_GLOBAL_OPTIONS:()=>i,ADB_MANAGED_FORBIDDEN_COMMANDS:()=>s,ADB_WAIT_STATES:()=>o,ADB_WAIT_TRANSPORTS:()=>a,adoptAndroidAdbSerial:()=>h,androidAdbHostTarget:()=>p,androidAdbInvocation:()=>m,androidAdbPayloadWithoutSerial:()=>w,androidAdbSerialTarget:()=>f,androidManagedAdbEnvironment:()=>N,applyManagedAndroidAdbServer:()=>T,lowerAndroidAdbInvocation:()=>M,normalizeAndroidAdbInstallOptions:()=>r,parseAndroidAdbArgv:()=>b,requireAndroidAdbServerPort:()=>S,requireManagedAndroidAdbAddressing:()=>O,requireManagedAndroidAdbCommand:()=>k,requireManagedAndroidAdbSerial:()=>E,requireSameAndroidAdbServer:()=>C,requireUnconflictedAndroidAdbSelector:()=>D,serializeAndroidAdbInvocation:()=>g});function r(e){let{replace:t,...n}=e??{};return{installArgs:t?[`-r`]:[],execOptions:n}}const i={"-a":0,"-d":0,"-e":0,"-s":1,"-t":1,"-H":1,"-P":1,"-L":1,"--one-device":1,"--exit-on-write-error":0},a=[``,`usb-`,`local-`,`any-`],o=[`device`,`recovery`,`bootloader`,`sideload`,`sideload-window`],s=[`nodaemon`,`server`,`fork-server`,`kill-server`,`start-server`,`connect`,`disconnect`,`reconnect`,`attach`,`detach`,`pair`],c=new Set(s);function l(e){return e.startsWith(`wait-for-`)}function u(e){if(!l(e))return;let t=e.slice(9);return a.some(e=>t.startsWith(e)&&o.includes(t.slice(e.length)))?e:void 0}function d(e){return c.has(e)}function f(e,t){return{selector:{kind:`serial`,serial:e},server:t===void 0?{kind:`ambient`}:{kind:`port`,port:t}}}function p(){return{selector:{kind:`unspecified`},server:{kind:`ambient`}}}function m(e,t,n){return{target:e,command:t,...n?{rawArgv:n}:{}}}function h(e,t){return{...e,selector:{kind:`serial`,serial:t}}}function g(e){if(e.rawArgv)return[...e.rawArgv];let{target:t,command:n}=e,r=[];return t.server.kind===`port`&&r.push(`-P`,String(t.server.port)),t.selector.kind===`serial`&&r.push(`-s`,t.selector.serial),t.hostGlobals&&r.push(...t.hostGlobals),t.waitFor&&r.push(t.waitFor),r.push(...n),r}const _={"-s":`serial`,"-P":`server`};function v(e,t){let n=e[t],r=u(n);if(r)return{kind:`wait`,waitFor:r,next:t+1};if(l(n))return{kind:`unknown-wait`,token:n,next:t+1};let a=_[n];if(a===void 0){if(!n.startsWith(`-`))return{kind:`stop`,next:t};let r=i[n]??0;return{kind:`global`,tokens:[n,...e.slice(t+1,t+1+r)],next:t+1+r}}let o=e[t+1]??``;if(a===`serial`)return{kind:`serial`,serial:o,next:t+2};let s=Number(o);return Number.isInteger(s)?{kind:`server`,port:s,next:t+2}:{kind:`global`,tokens:[n,o],next:t+2}}function y(e,t){e.kind===`wait`?t.waitFor===void 0?t.waitFor=e.waitFor:t.hostGlobals.push(e.waitFor):e.kind===`unknown-wait`?t.hostGlobals.push(e.token):e.kind===`serial`?t.selector.kind===`unspecified`?t.selector={kind:`serial`,serial:e.serial}:t.selector.serial!==e.serial&&t.hostGlobals.push(`-s`,e.serial):e.kind===`server`?t.server={kind:`port`,port:e.port}:e.kind===`global`&&t.hostGlobals.push(...e.tokens)}function b(e){let t=p(),n={selector:t.selector,server:t.server,waitFor:void 0,hostGlobals:[]},r=0;for(;;){let t=r<e.length?v(e,r):{kind:`stop`,next:r};if(t.kind===`stop`)break;y(t,n),r=t.next}let{selector:i,server:a,waitFor:o,hostGlobals:s}=n,c={selector:i,server:a,...o?{waitFor:o}:{},...s.length>0?{hostGlobals:s}:{}},l=s.length>0||o!==void 0||i.kind!==`unspecified`||a.kind===`port`;return{target:c,command:r===0?e:e.slice(r),rawArgv:l?e:void 0}}function x(e){if(e.rawArgv===void 0)return e.target.server.kind===`port`?e.target.server.port:void 0}function S(e,t){return C(x(e),t?.serverPort)}function C(e,t){if(e!==void 0&&t!==void 0&&e!==t)throw j(`server`);return e??t}function w(e,t){let n=0;for(;;){let r=n<e.length?v(e,n):{kind:`stop`,next:n};if(r.kind===`stop`)return;if(r.kind===`serial`)return r.serial===t?[...e.slice(0,n),...e.slice(n+2)]:void 0;n=r.next}}function T(e,t){let{target:n,command:r}=e;return O(n,t.port),k(r),m({selector:n.selector,server:{kind:`port`,port:t.port},...n.waitFor?{waitFor:n.waitFor}:{}},r)}function E(e,t){return D(e.selector,t),{...e,selector:{kind:`serial`,serial:t}}}function D(e,t){if(e.kind===`serial`&&e.serial!==t)throw j(`device`)}function O(e,t){if(e.hostGlobals)throw j(`target`);C(t,e.server.kind===`port`?e.server.port:void 0)}function k(e){if(d(e.find(e=>!l(e))??``))throw j(`target`)}const A={device:`Managed ADB transport cannot address another device.`,target:`Managed ADB transport cannot select another target.`,server:`Managed ADB transport cannot select another server.`};function j(e){throw new t(`COMMAND_FAILED`,A[e],{reason:`managed-device-transport-mismatch`})}function M(e,t,n){let{serverPort:r,...i}=t??{},a=S(e,t),o=a===void 0?e:T(e,{port:a}),s=a===void 0?void 0:N(o.target,n,i.env);return{args:g(o),options:{...i,...s===void 0?{}:{env:s}}}}function N(e,t,n){return e.server.kind===`port`?{...t,...n??{},ADB_SERVER_SOCKET:void 0,ANDROID_ADB_SERVER_PORT:String(e.server.port),ANDROID_ADB_SERVER_ADDRESS:`127.0.0.1`}:n}export{w as a,M as c,O as d,E as f,g as h,m as i,r as l,D as m,h as n,f as o,C as p,p as r,T as s,n as t,b as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime.js";import{C as t,w as n}from"./sdk-contracts.js";import{c as r,d as i,f as a,l as o,s,u as c,x as l}from"./owner-identity.js";import{c as u}from"./exec.js";import{t as
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{C as t,w as n}from"./sdk-contracts.js";import{c as r,d as i,f as a,l as o,s,u as c,x as l}from"./owner-identity.js";import{c as u}from"./exec.js";import{n as d,t as f}from"./file.js";import"./command.js";import"./process.js";import{O as p,S as m,a as h,b as g,c as _,d as v,l as y,p as b,s as x,v as S}from"./host-file.js";import{n as C}from"./agent-browser-process-record.js";import{r as w}from"./agent-browser-lifecycle.js";import T from"node:path";import E from"node:crypto";async function D(e){x(e.packageRoot);let t=ee([`install`,`--prefix`,e.packageRoot,`--no-global`,`--no-audit`,`--no-fund`,`--no-save`,e.packageSpec]);await u(t.command,t.args,{env:r(),timeoutMs:e.timeoutMs})}function O(e){p(T.join(e.installDir,`manifest.json`),JSON.stringify({package:e.packageName,version:e.version,node:c(),installedAt:new Date().toISOString()},null,2))}function ee(e){if(i()!==`win32`)return{command:`npm`,args:e};let n=k(r());if(!n)throw new t(`TOOL_MISSING`,`npm not found in PATH`,{nodeExecPath:o(),hint:"Install Node.js with npm, or add npm to PATH, and run `agent-device web setup` again."});return{command:o(),args:[n,...e]}}function k(e){let t=e.npm_execpath?.trim();if(t){let e=T.resolve(t);if(T.basename(e)===`npm-cli.js`&&A(e))return e}let n=T.join(T.dirname(o()),`node_modules`,`npm`,`bin`,`npm-cli.js`);return A(n)?n:void 0}function A(e){try{return v(e).isFile()}catch{return!1}}var j=e({doctorManagedAgentBrowser:()=>R,getManagedAgentBrowserStatus:()=>z,mapManagedAgentBrowserError:()=>$,runManagedAgentBrowser:()=>I,setupManagedAgentBrowser:()=>L});const M=`0.27.1`,N=`agent-browser`,P=3e5,F=6e4;async function I(e,t){let n=z({stateDir:t.stateDir});if(!n.installed)throw J(n);return await B(n,e,t)}async function L(e){let t=z(e);X(t.nodeMajor);let n=a();return await d({acquire:()=>f({lockDirPath:T.join(t.installDir,`..`,`.agent-browser-install.lock`),owner:{pid:n,startTime:l(n),acquiredAtMs:Date.now()},timeoutMs:P,description:`managed agent-browser setup`}),task:async()=>{let t=z(e);if(t.installed)return t;x(t.installDir),await D({packageRoot:T.join(t.installDir,`package`),packageSpec:`${N}@${M}`,timeoutMs:P});let n=z(e);if(!n.entryScript)throw Y(n);return await B(n,[`install`],{timeoutMs:P}),await B(n,[`doctor`,`--offline`,`--quick`],{timeoutMs:F}),O({installDir:n.installDir,packageName:N,version:M}),await z(e)}})}async function R(e){let t=z(e);if(!t.installed)throw J(t);return{status:t,...await B(t,[`doctor`,`--offline`,`--quick`],{timeoutMs:F,allowFailure:!0})}}function z(e){let t=e.stateDir??r().AGENT_DEVICE_STATE_DIR??ne(),n=T.join(t,`tools`,`agent-browser`,M),i=K(n),a=q(n),o=W(i),s=T.join(n,`home`),l=Z(n),u=Q(n),d=o!==void 0&&U(n),f=Number.parseInt(c().replace(/^v/,``).split(`.`)[0]??`0`,10);return{version:M,stateDir:t,installDir:n,packageDir:i,binaryPath:a,entryScript:o,homeDir:s,runtimeHomeDir:l,socketDir:u,installed:d,nodeMajor:f,nodeSupported:f>=24}}async function B(e,t,n){if(!e.entryScript)throw J(e);return await u(o(),[e.entryScript,...t],{allowFailure:n.allowFailure,env:V(e,r()),timeoutMs:n.timeoutMs,signal:n.signal})}function V(e,t){return x(e.homeDir),H(e),x(e.socketDir),{...t,HOME:e.runtimeHomeDir,AGENT_BROWSER_SOCKET_DIR:e.socketDir,AGENT_BROWSER_IDLE_TIMEOUT_MS:String(w(t)),AGENT_BROWSER_ARGS:C(t.AGENT_BROWSER_ARGS,e)}}function H(e){if(e.runtimeHomeDir!==e.homeDir){x(T.dirname(e.runtimeHomeDir));try{let t=y(e.runtimeHomeDir);if(t.isSymbolicLink()&&S(e.runtimeHomeDir)===e.homeDir||t.isDirectory())return;t.isSymbolicLink()&&m(e.runtimeHomeDir)}catch(e){if(!te(e))throw e}try{h(e.homeDir,e.runtimeHomeDir)}catch{x(e.runtimeHomeDir)}}}function U(e){return _(T.join(e,`manifest.json`))}function W(e){let t;try{let n=JSON.parse(g(T.join(e,`package.json`)));t=typeof n==`object`&&n?n.bin:void 0}catch{return}let n=typeof t==`string`?t:typeof t==`object`&&t?t[N]:void 0;if(typeof n!=`string`)return;let r=T.resolve(e,n);return G(r)?r:void 0}function G(e){try{return v(e).isFile()}catch{return!1}}function K(e){return T.join(e,`package`,`node_modules`,N)}function q(e){let t=i()===`win32`?`${N}.cmd`:N;return T.join(e,`package`,`node_modules`,`.bin`,t)}function J(e){return new t(`TOOL_MISSING`,`Managed web browser backend is not installed.`,{version:M,installDir:e.installDir,hint:e.nodeSupported===!1?`Web automation requires Node 24+; current Node is ${c()}.`:"Run `agent-device web setup` to install the managed web backend."})}function Y(e){return new t(`TOOL_MISSING`,`Managed web backend install produced no runnable entry.`,{version:M,installDir:e.installDir,packageDir:e.packageDir,hint:`Remove ${e.installDir} and run \`agent-device web setup\` again.`})}function X(e){if(!(e>=24))throw new t(`UNSUPPORTED_OPERATION`,`Web automation requires Node 24 or newer.`,{currentNode:c(),requiredNodeMajor:24,hint:`Run agent-device with Node 24+ for web setup and web automation.`})}function Z(e){if(i()===`win32`)return T.join(e,`home`);let t=E.createHash(`sha1`).update(e).digest(`hex`).slice(0,12);return T.join(b(),`agent-device-web`,t)}function Q(e){let t=E.createHash(`sha1`).update(e).digest(`hex`).slice(0,12);return T.join(b(),`adw`,t)}function te(e){return typeof e==`object`&&!!e&&`code`in e&&e.code===`ENOENT`}function ne(){return T.join(r().HOME??s(),`.agent-device`)}function $(e){let r=n(e);return r.code===`TOOL_MISSING`?new t(r.code,r.message,{...r.details??{},hint:typeof r.details?.hint==`string`?r.details.hint:"Run `agent-device web setup` to install the managed web backend."}):r}export{I as i,z as n,$ as r,j as t};
|
package/dist/src/android-adb.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import{d as e}from"./adb-executor.js";import{_ as t,d as n,h as r,n as i,p as a,t as o,v as s,y as c}from"./mechanics.js";import"./platform-runtime-android-adb-host.js";async function l(e,t){let{getAndroidAppStateWithAdb:n}=await import(`./platform-runtime.js`).then(e=>e.a);return await n(e,t)}export{o as captureAndroidLogcatWithAdb,e as createAndroidPortReverseManager,n as dismissAndroidKeyboardWithAdb,s as forceStopAndroidAppWithAdb,l as getAndroidAppStateWithAdb,a as getAndroidKeyboardStatusWithAdb,i as listAndroidAppsWithAdb,c as openAndroidAppWithAdb,r as readAndroidClipboardWithAdb,t as writeAndroidClipboardWithAdb};
|
package/dist/src/android.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime.js";import{c as t}from"./diagnostics.js";import"./diagnostics2.js";import
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{c as t}from"./diagnostics.js";import"./diagnostics2.js";import{u as n}from"./adb-executor.js";import{A as r,C as i,D as a,E as o,M as s,O as c,S as l,T as u,a as d,b as f,c as p,f as m,g as h,i as g,j as _,k as v,l as y,m as b,o as x,s as S,u as C,w,x as T}from"./mechanics.js";import{a as E,i as D,n as O}from"./app-lifecycle.js";import"./platform-runtime-android-adb-host.js";import{n as k}from"./scoped-provider.js";import{t as A}from"./snapshot-state.js";var j=e({createAndroidInteractor:()=>N});function M(e){return e?`daemon-session`:`command`}function N(e,j,N){let P=M(N?.appBundleId),F=t=>({...t===void 0?{}:{timeoutMs:t},captureNodes:async()=>{let t=await p(e,{includeHiddenContentHints:!1});return A(y(t),void 0).nodes}}),I={open:(t,n)=>D(e,t,{activity:n?.activity,appBundleId:n?.appBundleId,launchArgs:n?.launchArgs,url:n?.url}),openDevice:()=>E(e),close:t=>O(e,t),tap:(t,n)=>o(e,t,n),doubleTap:async(t,n)=>{await o(e,t,n),await o(e,t,n)},longPress:(t,n,r)=>u(e,t,n,r),focus:(t,n)=>i(e,t,n),type:(t,n)=>d(e,t,n),fill:(t,n,r,i)=>g(e,t,n,r,i,{helperSessionScope:P}),scroll:(t,n)=>v(e,t,{...n,helperSessionScope:P}),performGesture:t=>_(e,t),gestureViewport:()=>s(e,{helperSessionScope:P}),screenshot:(t,n)=>x(e,t,n),readTextAtPoint:async(t,n)=>{let{readAndroidTextAtPoint:r}=await import(`./mechanics.js`).then(e=>e.r);return await r(e,t.x,t.y,{helperSessionScope:M(n?.appBundleId)})??void 0},snapshot:async n=>{let r=n??{},i=await t(`snapshot_capture`,async()=>await p(e,{appBundleId:r.appBundleId,signal:r.signal??N?.signal,interactiveOnly:r.interactiveOnly,depth:r.depth,scope:r.scope,raw:r.raw,includeHiddenContentHints:r.includeHiddenContentHints,helperSessionScope:M(r.appBundleId)}),{backend:`android`});return y(i)},back:t=>l(e),home:()=>w(e),setOrientation:t=>r(e,t),appSwitcher:()=>T(e),tvRemote:(t,n)=>c(e,t,n),keyboardStatus:async()=>({kind:`ime-probe`,...await m(e)}),keyboardDismiss:async()=>({kind:`ime-probe`,...await C(e)}),keyboardEnter:async()=>(await a(e),{kind:`android-acknowledged`}),readClipboard:()=>b(e),writeClipboard:t=>h(e,t),setSetting:(t,n,r,i)=>S(e,t,n,r,i),readAlert:async()=>await f(e,`get`,F()),awaitAlert:async t=>await f(e,`wait`,F(t?.timeoutMs)),acceptAlert:async()=>await f(e,`accept`,F()),dismissAlert:async()=>await f(e,`dismiss`,F())};return j?k(I,t=>n(j,{serial:e.id},t)):I}export{N as n,j as t};
|
package/dist/src/app-helpers.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e}from"./app-inventory.js";import"./device.js";import{n as t}from"./adb-failure.js";import
|
|
1
|
+
import{n as e}from"./app-inventory.js";import"./device.js";import"./adb-executor.js";import{n as t}from"./adb-failure.js";import{n}from"./app-deployment-resolution.js";import{a as r,i}from"./app-parsers.js";const a=`android.intent.category.LAUNCHER`,o=`android.intent.category.LEANBACK_LAUNCHER`;async function s(t,r={}){let i=await c(t,r.target??`auto`);return(e(r.filter)===`user-installed`?(await f(t)).filter(e=>i.has(e)):Array.from(i)).map(e=>({package:e,name:n(e)})).sort((e,t)=>e.package.localeCompare(t.package))}async function c(e,t){let n=(await Promise.all(l(t).map(async t=>{let n=await e(u(t),{allowFailure:!0});return n.exitCode===0?d(n.stdout):[]}))).flat();return new Set(n)}function l(e){switch(e){case`mobile`:return[a];case`tv`:return[o];default:return[a,o]}}function u(e){return[`shell`,`cmd`,`package`,`query-activities`,`--brief`,`-a`,`android.intent.action.MAIN`,`-c`,e]}function d(e){return e.trim().length===0?[]:i(e)}async function f(e){let n=await e([`shell`,`pm`,`list`,`packages`,`-3`],{allowFailure:!0});if(n.exitCode!==0)throw t(`Failed to list Android user-installed apps`,n);return r(n.stdout)}export{s as listAndroidAppsWithAdb};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime.js";import{C as t,w as n}from"./sdk-contracts.js";import{r}from"./sdk-batch-runner.js";import{h as i,u as a}from"./exec.js";import{t as o}from"./timeouts.js";import{r as s}from"./command.js";import{i as c,n as l}from"./retry.js";import{
|
|
2
|
-
`).some(e=>{let t=e.toLowerCase();return t.startsWith(`error:`)&&(t.includes(`activity not started`)||t.includes(`unable to resolve intent`))})}function
|
|
3
|
-
`).map(e=>e.trim()).filter(Boolean);for(let e=t.length-1;e>=0;--e){let n=t[e];if(n===void 0||!n.includes(`/`))continue;let r=n.split(/\s+/)[0];if(r!==void 0)return r}return null}async function
|
|
1
|
+
import{r as e}from"./rolldown-runtime.js";import{C as t,w as n}from"./sdk-contracts.js";import{r}from"./sdk-batch-runner.js";import{h as i,u as a}from"./exec.js";import{t as o}from"./timeouts.js";import{r as s}from"./command.js";import{i as c,n as l}from"./retry.js";import{d as u,h as d,m as f,o as p}from"./adb-executor.js";import{i as m,o as h}from"./adb-transport.js";import{n as g}from"./adb-failure.js";import{r as _}from"./adb.js";import{n as v,t as ee}from"./boot-diagnostics.js";import{n as y,r as b,t as te}from"./app-deployment-resolution.js";import{a as ne,i as re}from"./app-parsers.js";import{n as ie}from"./window-state.js";import x from"node:path";const ae=[`emulator`,`platform-tools`,x.join(`cmdline-tools`,`latest`,`bin`),x.join(`cmdline-tools`,`tools`,`bin`)];function S(e){let t=new Set,n=[];for(let r of e){let e=r.trim();!e||t.has(e)||(t.add(e),n.push(e))}return n}function C(e=f().environment){let t=e.ANDROID_SDK_ROOT?.trim(),n=e.ANDROID_HOME?.trim(),r=e.HOME?.trim(),i=r?x.join(r,`Android`,`Sdk`):``;return S([t??``,n??``,i])}async function w(e=f().environment,t=f().files){let n=[],r;for(let i of C(e)){let e=[];for(let n of ae){let r=x.join(i,n);await t.isExecutable(r)&&e.push(r)}e.length!==0&&(r||=i,n.push(...e))}if(r&&(e.ANDROID_SDK_ROOT=e.ANDROID_SDK_ROOT?.trim()||r,e.ANDROID_HOME=e.ANDROID_HOME?.trim()||r),n.length===0)return;let i=(e.PATH??``).split(x.delimiter).map(e=>e.trim()).filter(e=>e.length>0);e.PATH=S([...n,...i]).join(x.delimiter)}const T=1e4;async function oe(e,n){await w();let r=e.avdName.trim();if(!r)throw new t(`INVALID_ARGS`,`Android emulator boot requires a non-empty AVD name.`);let o=e.timeoutMs??12e4;if(!await i(`adb`))throw new t(`TOOL_MISSING`,`adb not found in PATH`);if(!await i(`emulator`))throw new t(`TOOL_MISSING`,`emulator not found in PATH`);let s=await E(n,e.serial),c=D(s,r,e.serial);if(!c)throw new t(`DEVICE_NOT_FOUND`,`No Android emulator AVD named ${e.avdName}`,{requestedAvdName:r,availableAvds:s.map(e=>e.name),hint:"Run `emulator -list-avds` and pass an existing AVD name to --device."});let l=c.name,u=Date.now(),d=O(c)?c:void 0;if(!d){let t=[`-avd`,l];e.headless&&t.push(`-no-window`,`-no-audio`),a(`emulator`,t)}let f=d??await se({dependencies:n,avdName:l,serial:e.serial,timeoutMs:o}),p=Date.now()-u;return await j(f.id,Math.max(1e3,o-p)),{...(await E(n,e.serial)).find(e=>e.id===f.id)??f,name:l,booted:!0}}async function E(e,t){return await e.discoverLocal({platform:`android`,kind:`emulator`,...t?{serial:t}:{},...e.androidSerialAllowlist?{androidSerialAllowlist:[...e.androidSerialAllowlist]}:{}})}function D(e,t,n){let r=A(t);return e.find(e=>e.platform===`android`&&e.kind===`emulator`&&A(e.name)===r&&(!n||!O(e)||e.id===n))}function O(e){return k(e.id)}function k(e){return e.startsWith(`emulator-`)}function A(e){return e.toLowerCase().replaceAll(`_`,` `).replaceAll(/\s+/g,` `).trim()}async function se(e){let n=Date.now(),r=Math.min(1e3,Math.max(50,Math.floor(e.timeoutMs/20)));for(;Date.now()-n<e.timeoutMs;){try{let t=D(await E(e.dependencies,e.serial),e.avdName,e.serial);if(t&&O(t))return t}catch{}await o(r)}throw new t(`COMMAND_FAILED`,`Android emulator did not appear in time`,{avdName:e.avdName,serial:e.serial,timeoutMs:e.timeoutMs,hint:`Check emulator logs and verify the AVD can start from command line.`})}async function ce(e,t=T,n){return await d(m(h(e),[`shell`,`getprop`,`sys.boot_completed`]),{allowFailure:!0,signal:n,timeoutMs:t})}async function j(e,n=6e4,r){let i=l.fromTimeoutMs(n),a=Math.min(1e3,Math.max(50,Math.floor(n/20))),o=Math.max(1,Math.ceil(n/a)),s,u=!1;try{await c(async({deadline:a})=>{if(a?.isExpired())throw u=!0,new t(`COMMAND_FAILED`,`Android boot deadline exceeded`,{serial:e,timeoutMs:n,elapsedMs:i.elapsedMs(),message:`timeout`});let o=Math.max(1e3,a?.remainingMs()??n),c=await ce(e,Math.min(o,T),r);if(s=c,c.stdout.trim()!==`1`)throw new t(`COMMAND_FAILED`,`Android device is still booting`,{serial:e,stdout:c.stdout,stderr:c.stderr,exitCode:c.exitCode})},{maxAttempts:o,baseDelayMs:a,maxDelayMs:a,jitter:0,shouldRetry:e=>{let t=v({error:e,stdout:s?.stdout,stderr:s?.stderr,context:{platform:`android`,phase:`boot`}});return t!==`ADB_TRANSPORT_UNAVAILABLE`&&t!==`ANDROID_BOOT_TIMEOUT`}},{deadline:i,phase:`boot`,signal:r,classifyReason:e=>v({error:e,stdout:s?.stdout,stderr:s?.stderr,context:{platform:`android`,phase:`boot`}})})}catch(t){le({error:t,serial:e,timeoutMs:n,deadline:i,lastBootResult:s,timedOut:u})}}function le(e){let t=n(e.error),r=ue(e,t);throw fe(t,r,e.timedOut,de(e,r))}function ue(e,t){let n=v({error:e.error,stdout:e.lastBootResult?.stdout,stderr:e.lastBootResult?.stderr,context:{platform:`android`,phase:`boot`}});return n===`BOOT_COMMAND_FAILED`&&t.message===`Android device is still booting`?`ANDROID_BOOT_TIMEOUT`:n}function de(e,t){return{serial:e.serial,timeoutMs:e.timeoutMs,elapsedMs:e.deadline.elapsedMs(),reason:t,hint:ee(t),stdout:e.lastBootResult?.stdout,stderr:e.lastBootResult?.stderr,exitCode:e.lastBootResult?.exitCode,...n(e.error).details??{}}}function fe(e,n,r,i){return r||n===`ANDROID_BOOT_TIMEOUT`?new t(`COMMAND_FAILED`,`Android device did not finish booting in time`,i):e.code===`TOOL_MISSING`?new t(`TOOL_MISSING`,e.message,i):n===`ADB_TRANSPORT_UNAVAILABLE`?new t(`COMMAND_FAILED`,e.message,i):new t(e.code,e.message,i,e.cause)}var pe=e({closeAndroidApp:()=>Z,isAmStartError:()=>J,listAndroidApps:()=>I,openAndroidApp:()=>U,openAndroidDevice:()=>X,parseAndroidLaunchComponent:()=>Y});const M=`android.intent.category.LAUNCHER`,N=`android.intent.category.LEANBACK_LAUNCHER`,P=`android.intent.category.DEFAULT`,F=new Set([`localhost`,`127.0.0.1`,`::1`,`[::1]`]);async function I(e,t){let n=await L(e);return(t===`user-installed`?(await B(e)).filter(e=>n.has(e)):Array.from(n)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:y(e)}))}async function L(e){let t=new Set;for(let n of z(e,{includeFallbackWhenUnknown:!0})){let r=await _(e,[`shell`,`cmd`,`package`,`query-activities`,`--brief`,`-a`,`android.intent.action.MAIN`,`-c`,n],{allowFailure:!0});if(r.exitCode===0&&r.stdout.trim().length!==0)for(let e of re(r.stdout))t.add(e)}return t}function R(e){return z(e)[0]??M}function z(e,t={}){return e.target===`tv`?[N]:e.target===`mobile`?[M]:t.includeFallbackWhenUnknown?[M,N]:[M]}async function B(e){let t=await _(e,[`shell`,`pm`,`list`,`packages`,`-3`]);return ne(t.stdout)}function me(e){let t;try{t=new URL(e)}catch{return null}let n=t.hostname.toLowerCase();if(!F.has(n)||!t.port)return null;let r=Number(t.port);return Number.isInteger(r)?`tcp:${r}`:null}async function V(e,n){let r=me(n);if(!r)return;let i=u(p(e));try{await i.ensure({local:r,remote:r})}catch(e){let n={localPort:r.replace(`tcp:`,``),operation:`adb reverse ${r} ${r}`};throw e instanceof t&&Object.assign(n,{hint:e.details?.hint,diagnosticId:e.details?.diagnosticId,logPath:e.details?.logPath}),new t(`COMMAND_FAILED`,`Failed to ensure Android port reverse ${r} before opening localhost URL`,n,e)}}function H(e){return(e.launchArgs??[]).map(s)}async function U(e,t,n){e.booted||await j(e.id);let i=xe(n),a=i.activity,o=t.trim();if(r(o)){await he(e,o,i);return}if(i.url!==void 0){await ge(e,t,i);return}let s=await b(e,t),c=R(e);if(s.type===`intent`){await _e(e,s.value,i);return}if(a){await ve(e,s.value,a,c,i);return}await ye(e,s.value,c,i)}async function he(e,n,r){if(r.activity)throw new t(`INVALID_ARGS`,`Activity override is not supported when opening a deep link URL`);await V(e,n),await _(e,[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.VIEW`,`-d`,s(n),...Se(r.appBundleId),...H(r)])}async function ge(e,n,i){if(i.activity)throw new t(`INVALID_ARGS`,`Activity override is not supported when opening an app-bound deep link URL`);let a=i.url?.trim()??``;if(!r(a))throw new t(`INVALID_ARGS`,`Android app-bound open requires a valid URL target`);await V(e,a);let o=await be(e,n,`app-bound open`);await _(e,[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.VIEW`,`-d`,s(a),`-p`,o,...H(i)])}async function _e(e,n,r){if(r.activity)throw new t(`INVALID_ARGS`,`Activity override requires a package name, not an intent`);await _(e,[`shell`,`am`,`start`,`-W`,`-a`,n,...H(r)])}async function ve(e,t,n,r,i){let a=n.includes(`/`)?n:`${t}/${n.startsWith(`.`)?n:`.${n}`}`;try{await _(e,W(a,r,i))}catch(n){throw await Ce(e,t,n),n}}async function ye(e,t,n,r){let i=await _(e,[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,P,`-c`,n,`-p`,t,...H(r)],{allowFailure:!0});if(i.exitCode===0&&!J(i.stdout,i.stderr))return;let a=await we(e,t);if(!a)throw await K(e,t)?g(`Failed to launch ${t}`,i):G(t);await _(e,W(a,n,r))}function W(e,t,n){return[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,P,`-c`,t,`-n`,e,...H(n)]}async function be(e,n,r){let i=await b(e,n);if(i.type===`intent`)throw new t(`INVALID_ARGS`,`Android ${r} requires a package name, not an intent`);return i.value}function xe(e){return typeof e==`string`?{activity:e}:e??{}}function Se(e){let t=e?.trim();return t?[`-p`,t]:[]}function G(e){return new t(`APP_NOT_INSTALLED`,`No package found matching "${e}"`,{package:e,hint:te})}async function K(e,t){let n=await _(e,[`shell`,`pm`,`path`,t],{allowFailure:!0}),r=`${n.stdout}\n${n.stderr}`;return n.exitCode===0&&/\bpackage:/i.test(r)?!0:(q(r),!1)}async function Ce(e,n,r){if(q(r instanceof t?`${String(r.details?.stdout??``)}\n${String(r.details?.stderr??``)}`:``)||!await K(e,n))throw G(n)}function q(e){return/\bunknown package\b/i.test(e)||/\bpackage .* (?:was|is) not found\b/i.test(e)||/\bpackage .* does not exist\b/i.test(e)||/\bcould not find package\b/i.test(e)}async function we(e,t){let n=Array.from(new Set(z(e,{includeFallbackWhenUnknown:!0})));for(let r of n){let n=await _(e,[`shell`,`cmd`,`package`,`resolve-activity`,`--brief`,`-a`,`android.intent.action.MAIN`,`-c`,r,t],{allowFailure:!0});if(n.exitCode!==0)continue;let i=Y(n.stdout);if(i)return i}return null}function J(e,t){return`${e}\n${t}`.split(`
|
|
2
|
+
`).some(e=>{let t=e.toLowerCase();return t.startsWith(`error:`)&&(t.includes(`activity not started`)||t.includes(`unable to resolve intent`))})}function Y(e){let t=e.split(`
|
|
3
|
+
`).map(e=>e.trim()).filter(Boolean);for(let e=t.length-1;e>=0;--e){let n=t[e];if(n===void 0||!n.includes(`/`))continue;let r=n.split(/\s+/)[0];if(r!==void 0)return r}return null}async function X(e){e.booted||await j(e.id)}async function Z(e,n){if(n.trim().toLowerCase()===`settings`){await _(e,[`shell`,`am`,`force-stop`,`com.android.settings`]),await Q(e,`com.android.settings`);return}let r=await b(e,n);if(r.type===`intent`)throw new t(`INVALID_ARGS`,`Close requires a package name, not an intent`);await _(e,[`shell`,`am`,`force-stop`,r.value]),await Q(e,r.value)}async function Q(e,t){await Te(e,t),await De(e,t)}async function Te(e,t){let n=Date.now()+2e3;for(;Date.now()<n;){if((await Ee(e))?.package!==t)return;await o(50)}}async function Ee(e){let t=await ie(e);return t.package?t:null}async function De(e,t){let n=Date.now()+2e3;for(;Date.now()<n;){if(!await $(e,t)&&(await o(150),!await $(e,t)))return;await o(50)}}async function $(e,t){return((await _(e,[`shell`,`pidof`,t],{allowFailure:!0})).stdout??``).trim().length>0}export{X as a,j as c,U as i,w as l,Z as n,Y as o,J as r,oe as s,pe as t,C as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./api.js";import{S as e,n as t,t as n}from"./ios-client.js";import{t as r}from"./async-lifecycle.js";async function i(t){try{return t.descriptor.platform===`ios`?await a(t):await o(t)}catch(t){if(t instanceof e)return{status:`missing`};throw t}}async function a(e){let t=await s(async()=>await e.limrun.iosInstances.get(e.descriptor.instanceId,{timeout:5e3,maxRetries:0,signal:e.signal}),e.descriptor);if(t.status!==`active`)return t;let{instance:r}=t,i=await n({apiUrl:t.apiUrl,token:r.status.token,logLevel:`warn`});return{status:`opened`,reader:{platform:`ios`,leaseId:e.descriptor.leaseId,instanceId:e.descriptor.instanceId,readLogs:async(e,t)=>await i.appLogTail(e,t),[Symbol.asyncDispose]:async()=>i.disconnect()}}}async function o(e){let n=await s(async()=>await e.limrun.androidInstances.get(e.descriptor.instanceId,{timeout:5e3,maxRetries:0,signal:e.signal}),e.descriptor);if(n.status!==`active`)return n;let{instance:i}=n;if(!i.status.adbWebSocketUrl)return{status:`missing`};let a=await t({apiUrl:n.apiUrl,adbUrl:i.status.adbWebSocketUrl,token:i.status.token,logLevel:`warn`}),o=new r,c=!1;o.defer(async()=>{c||a.disconnect()});try{let t=await a.startAdbTunnel();o.defer(async()=>{c||t.close()});let n=`${t.address.address}:${t.address.port}`,r=async(t,r)=>await e.dependencies.host.runAdb(
|
|
1
|
+
import"./api.js";import{S as e,n as t,t as n}from"./ios-client.js";import{t as r}from"./async-lifecycle.js";async function i(t){try{return t.descriptor.platform===`ios`?await a(t):await o(t)}catch(t){if(t instanceof e)return{status:`missing`};throw t}}async function a(e){let t=await s(async()=>await e.limrun.iosInstances.get(e.descriptor.instanceId,{timeout:5e3,maxRetries:0,signal:e.signal}),e.descriptor);if(t.status!==`active`)return t;let{instance:r}=t,i=await n({apiUrl:t.apiUrl,token:r.status.token,logLevel:`warn`});return{status:`opened`,reader:{platform:`ios`,leaseId:e.descriptor.leaseId,instanceId:e.descriptor.instanceId,readLogs:async(e,t)=>await i.appLogTail(e,t),[Symbol.asyncDispose]:async()=>i.disconnect()}}}async function o(e){let n=await s(async()=>await e.limrun.androidInstances.get(e.descriptor.instanceId,{timeout:5e3,maxRetries:0,signal:e.signal}),e.descriptor);if(n.status!==`active`)return n;let{instance:i}=n;if(!i.status.adbWebSocketUrl)return{status:`missing`};let a=await t({apiUrl:n.apiUrl,adbUrl:i.status.adbWebSocketUrl,token:i.status.token,logLevel:`warn`}),o=new r,c=!1;o.defer(async()=>{c||a.disconnect()});try{let t=await a.startAdbTunnel();o.defer(async()=>{c||t.close()});let n=`${t.address.address}:${t.address.port}`,r=async(t,r)=>await e.dependencies.host.runAdb(e.dependencies.android.deviceAdbInvocation(n,t),r),i={platform:`android`,leaseId:e.descriptor.leaseId,instanceId:e.descriptor.instanceId,readLogs:async(t,n)=>await e.dependencies.android.readLogs(r,n),[Symbol.asyncDispose]:async()=>{await e.dependencies.host.runAdb(e.dependencies.android.hostAdbInvocation([`disconnect`,n]),{allowFailure:!0,timeoutMs:1e4}).catch(()=>void 0);let r=(await Promise.allSettled([Promise.resolve().then(()=>t.close()),Promise.resolve().then(()=>a.disconnect())])).flatMap(e=>e.status===`rejected`?[e.reason]:[]);if(r.length===1)throw r[0];if(r.length>1)throw AggregateError(r,`Limrun Android app-log reader cleanup failed`)}};return c=!0,{status:`opened`,reader:i}}finally{await o[Symbol.asyncDispose]()}}async function s(e,t){let n=await e();return c(n.metadata.labels,t)?n.status.state===`terminated`||!n.status.apiUrl?{status:`missing`}:{status:`active`,instance:n,apiUrl:n.status.apiUrl}:{status:`ownership-lost`}}function c(e,t){return e?.provider===`limrun`&&e.leaseId===t.leaseId}export{i as reconnectLimrunAppLogReader};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{C as e}from"./sdk-contracts.js";import{l as t}from"./sdk-device.js";import{Jt as n,Xt as r}from"./sdk-batch.js";import{n as i,o as a,r as o,s}from"./request-cancellation.js";import{n as c,t as l}from"./application-lifecycle-runtime.js";import{i as u,n as d}from"./touch-runtime.js";import{A as ee,B as te,D as ne,E as re,F as ie,G as f,H as p,I as ae,L as m,M as oe,N as h,R as g,W as se,a as ce,b as _,d as v,g as y,i as le,k as ue,m as de,s as fe,t as pe,v as b,w as me,x}from"./alert-runtime.js";import{n as he}from"./audio-probe-runtime.js";import{n as ge}from"./perf-runtime.js";import{r as _e}from"./platform-runtime-unavailable.js";import{a as ve,n as ye}from"./durable-resource.js";import{t as be}from"./async-lifecycle.js";import{a as S,d as xe,f as Se,n as Ce,o as we,u as Te}from"./src7.js";import{i as Ee,t as De}from"./gesture-admission.js";import{n as Oe}from"./interactor-operation-catalog.js";import{t as C}from"./app-log-runtime.js";import{r as ke,t as Ae}from"./application-lifecycle-interaction.js";import{setTimeout as je}from"node:timers/promises";const w=Object.freeze({available:!0}),Me=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose portable gesture execution yet.`}),Ne=Object.freeze({available:!1,reason:`unsupported-provider-mode`}),Pe=Object.freeze({available:!1,reason:`unsupported-provider-mode`}),Fe=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:De}),Ie=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:Ee});function T(e,t){if(!t.available)return h({unsupported:t});if(e.platform!==`android`)return h({unsupported:Me});let n=e.target===`tv`;return h({unsupported:Ne,plan:w,directionalFling:w,multiTouch:n?Fe:w,targetAuthoredDrag:n?Ie:w,viewport:w})}const Le=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose home yet.`}),Re=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose tv remote control.`}),ze=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`tv-remote is supported only on Android TV targets.`}),Be=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose keyboard actions.`}),Ve=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose clipboard access yet.`}),He=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose settings changes yet.`}),Ue=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose app switcher yet.`});function E(e,n){let r=n??w,i=Object.freeze({available:!1,reason:`unsupported-provider-mode`});return Object.freeze({...ae({focus:r}),...ne({type:r}),...u({unsupported:i,tap:r,longPress:
|
|
1
|
+
import{C as e}from"./sdk-contracts.js";import{l as t}from"./sdk-device.js";import{Jt as n,Xt as r}from"./sdk-batch.js";import{n as i,o as a,r as o,s}from"./request-cancellation.js";import{n as c,t as l}from"./application-lifecycle-runtime.js";import{i as u,n as d}from"./touch-runtime.js";import{A as ee,B as te,D as ne,E as re,F as ie,G as f,H as p,I as ae,L as m,M as oe,N as h,R as g,W as se,a as ce,b as _,d as v,g as y,i as le,k as ue,m as de,s as fe,t as pe,v as b,w as me,x}from"./alert-runtime.js";import{n as he}from"./audio-probe-runtime.js";import{n as ge}from"./perf-runtime.js";import{r as _e}from"./platform-runtime-unavailable.js";import{a as ve,n as ye}from"./durable-resource.js";import{t as be}from"./async-lifecycle.js";import{a as S,d as xe,f as Se,n as Ce,o as we,u as Te}from"./src7.js";import{i as Ee,t as De}from"./gesture-admission.js";import{n as Oe}from"./interactor-operation-catalog.js";import{t as C}from"./app-log-runtime.js";import{r as ke,t as Ae}from"./application-lifecycle-interaction.js";import{setTimeout as je}from"node:timers/promises";const w=Object.freeze({available:!0}),Me=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose portable gesture execution yet.`}),Ne=Object.freeze({available:!1,reason:`unsupported-provider-mode`}),Pe=Object.freeze({available:!1,reason:`unsupported-provider-mode`}),Fe=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:De}),Ie=Object.freeze({available:!1,reason:`unsupported-platform-leaf`,hint:Ee});function T(e,t){if(!t.available)return h({unsupported:t});if(e.platform!==`android`)return h({unsupported:Me});let n=e.target===`tv`;return h({unsupported:Ne,plan:w,directionalFling:w,multiTouch:n?Fe:w,targetAuthoredDrag:n?Ie:w,viewport:w})}const Le=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose home yet.`}),Re=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose tv remote control.`}),ze=Object.freeze({available:!1,reason:`unsupported-device-kind`,hint:`tv-remote is supported only on Android TV targets.`}),Be=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose keyboard actions.`}),Ve=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose clipboard access yet.`}),He=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose settings changes yet.`}),Ue=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose app switcher yet.`});function E(e,n){let r=n??w,i=Object.freeze({available:!1,reason:`unsupported-provider-mode`});return Object.freeze({...ae({focus:r}),...ne({type:r}),...u({unsupported:i,tap:r,longPress:r,hover:n??i,fill:r,tapElementSelector:n??(t(e)?r:i)}),...T(e,r),...ee({scroll:r})})}function We(e){let{device:t,signal:n}=e,r=n=>e.getInteractor(t,n);return Object.freeze({...te({device:t,signal:n,resolveInteractor:r,presentIosAcquisition:e.presentIosAcquisition}),...ie({device:t,signal:n,resolveInteractor:r}),...re({device:t,signal:n,resolveInteractor:r}),...d({device:t,signal:n,resolveInteractor:r,facts:E(t),pause:async e=>await je(e,void 0,{signal:n})}),...se({device:t,signal:n,resolveInteractor:r}),...oe({device:t,signal:n,facts:T(t,w),resolveInteractor:r}),...ue({device:t,signal:n,resolveInteractor:r})})}function D(e,t){return t?Object.freeze({...x({back:t}),..._({home:t}),...b({orientation:t}),...y({tvRemote:t})}):e.platform===`android`?Object.freeze({...x({back:w}),..._({home:w}),...b({orientation:w}),...y({tvRemote:e.target===`tv`?w:ze})}):Object.freeze({...x({back:w}),..._({home:Le}),...b({orientation:w}),...y({tvRemote:Re})})}function O(e,t){return t?Object.freeze({...v({unsupported:t})}):e.platform===`android`?Object.freeze({...v({unsupported:Pe,read:w,write:w})}):Object.freeze({...v({unsupported:Ve})})}const Ge=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS direct sessions do not expose alert inspection yet.`});function k(e,t){let n=t??(e.platform===`android`?w:Ge);return Object.freeze({...pe({read:n,wait:n,accept:n,dismiss:n})})}function A(e,t){let n=t??(e.platform===`android`?w:Ue);return Object.freeze({...fe({appSwitcher:n})})}function j(e,t){return Object.freeze({...ce({triggerAppEvent:t??w})})}function M(e,t){let n=t??(e.platform===`android`?w:He);return Object.freeze({...le({setSetting:n})})}function N(e,t){let n=t??Be,r=t===void 0&&e.platform===`android`;return Object.freeze({...de(r?{unsupported:n,status:w,dismiss:w,enter:w}:{unsupported:n})})}const P=Object.freeze({resourceKind:C,version:1,encode:e=>({...e}),decode:e=>e.transport!==`limrun-log-poller`||e.platform!==`ios`&&e.platform!==`android`||!F(e.leaseId)||!F(e.instanceId)||!F(e.appBundleId)||!F(e.outputPath)?{status:`invalid`,message:`Invalid Limrun app-log descriptor`}:{status:`decoded`,descriptor:Object.freeze({transport:`limrun-log-poller`,platform:e.platform,leaseId:e.leaseId,instanceId:e.instanceId,appBundleId:e.appBundleId,outputPath:e.outputPath})}});function Ke(e){if(e.device.platform===`apple`&&!e.device.appleOs)throw TypeError(`Limrun Apple app-log persistence requires an explicit appleOs identity`);return ye({resourceKind:C,sessionId:e.sessionId,device:{id:e.device.id,family:e.device.platform,...e.device.appleOs===void 0?{}:{appleOs:e.device.appleOs},kind:e.device.kind,...e.device.target===void 0?{}:{target:e.device.target},...e.device.iosPhysicalDeviceBackend===void 0?{}:{iosPhysicalDeviceBackend:e.device.iosPhysicalDeviceBackend}},owner:e.owner,fence:e.fence,lifecycle:`open`,descriptor:ve(P,e.descriptor)})}function F(e){return typeof e==`string`&&e.trim().length>0}async function I(e){let t=new be,n=!1;t.defer(async()=>{n||await e.reader[Symbol.asyncDispose]()});try{let r=await e.host.outputs.readTail(e.outputPath,262144),i=await e.host.outputs.openAppend(e.outputPath);t.defer(async()=>{n||await i[Symbol.asyncDispose]()});let a=qe(e,i,Qe(r));return n=!0,a}finally{await t[Symbol.asyncDispose]()}}function qe(e,t,n){let r=et(e.reader),i=e.host.clock.now(),a=`active`,o=!1,s=n,c=(async()=>{for(;!o;){try{let n=await Je(e);if(n.status===`timeout`){a=`failed`;return}if(o)return;let r=Ye(s,n.text);s=n.text,r&&await t.write(r.endsWith(`
|
|
2
2
|
`)?r:`${r}\n`),a=`active`}catch{if(o)return;a=`recovering`}await e.host.clock.sleep(1e3)}})(),l;return Te({inspect:()=>({backend:r,state:a,startedAt:i}),finish:async()=>l??=(async()=>(o=!0,await c,(await $e([e.reader,t])).length>0?(a=`failed`,{status:`cleanup-pending`,reason:`transport-failed`,message:`Limrun app-log cleanup did not settle every owned resource`}):(a=`ended`,{status:`completed`,result:{backend:r,outputPath:e.outputPath,completedAt:e.host.clock.now()}})))()})}async function Je(e){let t=new AbortController,n=i(e.reader.readLogs(e.appBundleId,1e3),t.signal,`App-log provider read aborted`).then(e=>({status:`read`,text:e}));try{let r=await Promise.race([n,e.host.clock.sleep(5e3,t.signal).then(()=>({status:`timeout`}))]);return r.status===`timeout`&&(t.abort(),await n.catch(()=>void 0)),r}finally{t.abort()}}function Ye(e,t){if(!e||!t)return t;let n=Xe(t),r=Math.min(e.length,t.length),i=e.slice(e.length-r);return t.slice(Ze(i,t,n))}function Xe(e){let t=new Uint32Array(e.length),n=0;for(let r=1;r<e.length;r+=1){for(;n>0&&e[r]!==e[n];)n=t[n-1];e[r]===e[n]&&(n+=1),t[r]=n}return t}function Ze(e,t,n){let r=0;for(let i=0;i<e.length;i+=1){for(;r>0&&e[i]!==t[r];)r=n[r-1];e[i]===t[r]&&(r+=1),r===t.length&&i<e.length-1&&(r=n[r-1])}return r}function Qe(e){return e.split(`
|
|
3
3
|
`).filter(e=>!e.startsWith(`[agent-device][mark]`)).join(`
|
|
4
4
|
`)}async function $e(e){return(await Promise.allSettled(e.map(async e=>await e[Symbol.asyncDispose]()))).flatMap(e=>e.status===`rejected`?[e.reason]:[])}function et(e){return e.platform===`ios`?`ios-simulator`:`android`}function tt(e){let t=Ae({owner:`Limrun`,openTargetIdentity:`bundle-id`,closeBeforeRelaunch:!0,configureProviderPortReverse:async t=>await e.configurePortReverse(t),binding:ke({device:e.device,signal:e.signal,resolveInteractor:t=>e.getInteractor(e.device,t)})}),n=e.resolveAppReference;return n?Object.freeze({...t,resolveOpenTarget:async e=>await t.resolveOpenTarget(nt(e,n)),openApplication:async e=>await t.openApplication(rt(e,n)),closeApplication:async e=>await t.closeApplication(it(e,n))}):t}function nt(e,t){return e.target===void 0?e:{...e,target:t(e.target)}}function rt(e,t){return{...e,target:R(e.target,t),positionals:L(e.positionals,t),appBundleId:R(e.appBundleId,t)}}function it(e,t){return{...e,positionals:L(e.positionals,t),appBundleId:R(e.appBundleId,t)}}function L(e,t){let n=e[0];return n===void 0?e:[t(n),...e.slice(1)]}function R(e,t){return e===void 0?void 0:t(e)}function at(e){let t=s(e.id);return!t||e.target!==`mobile`?!1:t.platform===`ios`?e.platform===`apple`&&e.appleOs===`ios`&&e.kind===`simulator`&&e.iosPhysicalDeviceBackend===void 0:e.platform===`android`&&e.appleOs===void 0&&e.kind===`emulator`&&e.iosPhysicalDeviceBackend===void 0}const ot=Object.freeze({available:!0}),z=Object.freeze({available:!1,reason:`owner-capability-missing`,hint:`The Limrun provider session is no longer active for this device.`}),st=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Push notifications are unavailable for Limrun provider-owned devices.`});function B(e,t){let n=lt(e,t);return Object.freeze({deployApp:n,materializeAppSource:n,deployMaterializedApp:n,sendPushNotification:V(e,t)?st:z})}function ct(e,t,n,r){let i=e.deployApp,a=e.deployMaterializedApp;return!B(e,t).deployApp.available||!i||!a?Object.freeze({}):Object.freeze({deployApp:async e=>H(await i(t,e,n,r)),materializeAppSource:async r=>await ut(e.host,t,r,n),deployMaterializedApp:async e=>H(await a(t,e,n,r))})}function lt(e,t){return at(t)&&V(e,t)&&e.deployApp&&e.deployMaterializedApp?ot:z}function V(e,t){return e.isSessionActive?.(t)??e.ownsDevice(t)}async function ut(e,t,n,r){return await(t.platform===`apple`?e.appleDeployment:e.androidDeployment).prepareArtifact(n,{signal:r})}function H(t){if(!t)throw new e(`UNSUPPORTED_OPERATION`,`The Limrun provider session is no longer active.`);return t}const U=Object.freeze({available:!0}),W=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Custom snapshot actions are available only for Limrun iOS simulator sessions.`}),dt=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun does not expose viewport resizing.`}),G=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun-owned devices read element text from the captured tree only.`}),K=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun does not expose an exact-owner screen-recording runtime.`}),ft=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Headless boot is unavailable for provider-owned devices.`}),q=Object.freeze({available:!1,reason:`owner-capability-missing`,hint:`Limrun requires a matching live provider session for this device.`}),pt=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Apple runner preparation is unavailable for Limrun-owned devices.`}),mt=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS appstate is session-owned; no sessionless provider foreground probe is exposed.`}),ht=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun open requires a Limrun-owned iOS simulator or Android emulator.`}),gt=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun close requires a Limrun-owned iOS simulator or Android emulator.`}),J=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Runtime hints are not applied to provider-owned devices.`}),_t=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun port reverse requires an active Android Limrun session.`}),Y=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun does not expose the audio probe.`});function vt(e){return{...e,isSessionActive:e.hasLiveSession}}function X(e,t){let n=yt(e,t),r=bt(e,t),i=xt(e,t);return l({resolveOpenTarget:n,prepareApplicationOpen:n,openApplication:n,applyRuntimeHints:J,clearRuntimeHints:J,closeApplication:r,finalizeApplicationClose:r,prepareAppleRunner:pt,configureProviderPortReverse:i})}function yt(e,t){return a(e)?t?U:q:ht}function bt(e,t){return a(e)?t?U:q:gt}function xt(e,t){return t?e.platform===`android`?U:_t:q}function Z(e,n){let r=B(vt(e),n),i=n.platform===`android`,a=t(n)&&n.kind===`simulator`?U:W;return Object.freeze({device:{family:n.platform,...n.appleOs===void 0?{}:{appleOs:n.appleOs},kind:n.kind,...n.target===void 0?{}:{target:n.target},...n.iosPhysicalDeviceBackend===void 0?{}:{iosPhysicalDeviceBackend:n.iosPhysicalDeviceBackend},providerMode:`provider-runtime`},operations:{appLogInspect:U,appLogDoctor:U,appLogStart:U,appLogReattach:U,appLogCleanup:U,...r,appState:i?U:mt,networkDump:U,screenRecordingStart:K,screenRecordingReattach:K,screenRecordingCleanup:K,...p({capture:U,customActions:a,withoutActiveApp:U}),...f({capture:U}),...g({findText:W}),...m({setViewport:dt}),...E(n),...me({readTextAtPoint:G}),...D(n),...N(n),...O(n),...A(n),...j(n),...M(n),...k(n),...he({capture:Y,query:Y}),...ge({frames:G,memorySample:G,memorySnapshot:G,nativeCapture:G,profileReport:G}),ensureReady:U,bootTarget:U,bootTargetHeadless:ft,listApps:U,shutdownTarget:{available:!1,reason:`unsupported-provider-mode`,hint:`Limrun owns the target lifecycle for provider-owned devices.`},...X(n,!0)}})}function St(e,t){let n=Z(e,t);return Object.freeze({device:n.device,operations:{...n.operations,appLogInspect:q,appLogDoctor:q,appLogStart:q,appLogReattach:U,appLogCleanup:U,appState:q,networkDump:q,screenRecordingStart:q,screenRecordingReattach:q,screenRecordingCleanup:q,...p({capture:q,customActions:q,withoutActiveApp:q}),...f({capture:q}),...g({findText:q}),...m({setViewport:q}),...E(t,q),...D(t,q),...N(t,q),...O(t,q),...A(t,q),...j(t,q),...M(t,q),...k(t,q),ensureReady:q,bootTarget:q,bootTargetHeadless:q,listApps:q,deployApp:q,materializeAppSource:q,deployMaterializedApp:q,sendPushNotification:q,shutdownTarget:q,...X(t,!1)}})}function Ct(t){let i=n(`limrun`,t.runtimeInstance),o=e=>a(e)&&t.ownsDevice(e),s=e=>o(e)&&t.hasLiveSession(e);return Object.freeze({owner:i,ownsDevice:o,inspectFacts:async e=>s(e)?Z(t,e):_e(e,i,{appLog:q,appState:q,appDeployment:q,network:q,screenshot:q,viewport:q,focus:q,gesture:q,scroll:q,typeText:q,touch:q,elementText:q,back:q,home:q,orientation:q,tvRemote:q,keyboard:q,clipboard:q,appSwitcher:q,triggerAppEvent:q,setSetting:q,readAlert:q,awaitAlert:q,acceptAlert:q,dismissAlert:q,audioProbeCapture:q,audioProbeQuery:q,perf:q,readiness:q,shutdown:q,lifecycle:X(e,!1)}),bind:async n=>{if(n.intent.kind===`exact-owner`&&!r(n.intent.owner,i))throw new e(`UNSUPPORTED_OPERATION`,`Limrun app-log owner identity does not match`);if(!a(n.device))throw new e(`UNSUPPORTED_PLATFORM`,`Limrun app logs require an iOS simulator or Android emulator device identity`);let o=s(n.device);if(n.intent.kind!==`exact-owner`&&!o)throw new e(`UNSUPPORTED_OPERATION`,`Limrun provider session is no longer live for the selected device`,{reason:`provider-session-unavailable`});return wt(t,i,n.device,n.scope.signal,!o)},shutdown:async()=>void 0})}function wt(t,n,r,i,a){let s=a?St(t,r):Z(t,r),l=o(),u=xe({codec:P,reattach:async(e,n)=>{if(!$(e,r)||!S(t.host,n.sessionId,e))return{status:`unreattachable`,reason:`descriptor-invalid`,message:`Limrun app-log descriptor does not match the bound device or owning session`};let a=await t.reconnect(e,i);return a.status===`missing`?{status:`missing`}:a.status===`ownership-lost`?{status:`unreattachable`,reason:`ownership-fence-lost`}:{status:`active`,handle:await I({host:t.host,reader:a.reader,appBundleId:e.appBundleId,outputPath:e.outputPath})}},cleanup:async(e,n)=>$(e,r)&&S(t.host,n.sessionId,e)?{status:`cleaned`}:{status:`cleanup-pending`,reason:`ownership-fence-lost`,message:`Limrun app-log descriptor does not match the bound device or owning session`}}),d={appLogInspect:async()=>({backend:Q(r)}),appLogDoctor:async()=>({backend:Q(r),checks:{limrunSessionAvailable:await Tt(t,r,i)},notes:[]}),appLogStart:async a=>{we(t.host,a),i.throwIfAborted();let o=await t.openCurrent(r);if(!o)throw new e(`UNSUPPORTED_OPERATION`,`Limrun app logs require an active instance`);let s={transport:`limrun-log-poller`,platform:o.platform,leaseId:o.leaseId,instanceId:o.instanceId,appBundleId:a.appBundleId,outputPath:a.outputPath},c=!1;try{i.throwIfAborted();let e=Ke({sessionId:a.sessionId,device:r,owner:n,fence:a.fence,descriptor:s});c=!0;let l=await I({host:t.host,reader:o,appBundleId:a.appBundleId,outputPath:a.outputPath});return Se(l,e)}catch(e){throw c||await o[Symbol.asyncDispose](),e}},...u,networkDump:async e=>{let n=await t.host.appLogs.readRecent(e.sessionId,e.maxScanLines),i=Q(r),{dump:a}=Ce(n.text,{...e,path:n.path,exists:n.exists,lineNumberOffset:n.skippedLines,backend:i}),o=a.entries.length===0?[`No HTTP(s) entries were found in recent session app logs.`]:[];return Object.freeze({source:`app-log`,backend:i,dump:a,notes:o})},ensureReady:async()=>({...r,booted:!0}),bootTarget:async()=>({...r,booted:!0}),listApps:async e=>await t.listApps(e.device,e.filter,i),...r.platform===`android`?{appState:async()=>await t.getAppState(r,i)}:{},...c(tt({device:r,signal:i,getInteractor:t.getInteractor,resolveAppReference:e=>t.resolveAppReference?.(r,e)??e,configurePortReverse:t.configurePortReverse}),s.operations),...We({device:r,signal:i,getInteractor:t.getInteractor,presentIosAcquisition:t.host.snapshot.presentIosAcquisition}),...Oe({device:r,signal:i,resolveInteractor:e=>t.getInteractor(r,e),facts:s.operations}),...ct(vt(t),r,i,l)};return Object.freeze({device:r,owner:n,facts:s,operations:Object.freeze(a?{appLogReattach:u.appLogReattach,appLogCleanup:u.appLogCleanup}:d),[Symbol.asyncDispose]:async()=>await l[Symbol.asyncDispose]()})}async function Tt(e,t,n){n.throwIfAborted();let r=await e.openCurrent(t);if(!r)return!1;try{n.throwIfAborted()}finally{await r[Symbol.asyncDispose]()}return!0}function Q(e){return e.platform===`apple`?`ios-simulator`:`android`}function $(e,t){if(!a(t))return!1;let n=s(t.id);return n!==void 0&&n.leaseId===e.leaseId&&n.platform===e.platform&&(t.platform===`apple`?e.platform===`ios`:e.platform===`android`)}export{Ct as createLimrunPlatformRuntimeOwner};
|
|
@@ -81,10 +81,9 @@ type AndroidAdbExecutorResult = {
|
|
|
81
81
|
/** Structural mirror of node's StdioOptions; R13 bars the child_process import that names it. */
|
|
82
82
|
type AndroidAdbStdioOption = 'overlapped' | 'pipe' | 'ignore' | 'inherit';
|
|
83
83
|
/**
|
|
84
|
-
* A spawned adb process is long-lived — the snapshot helper session rides it for
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* kill their own helper.
|
|
84
|
+
* A spawned adb process is long-lived — the snapshot helper session rides it for the whole session
|
|
85
|
+
* — so `timeoutMs` is not part of its options: background spawns arm no deadline, and a field that
|
|
86
|
+
* looked like one invited callers to kill their own helper.
|
|
88
87
|
*/
|
|
89
88
|
type AndroidAdbSpawnOptions = Omit<AndroidAdbExecutorOptions, 'timeoutMs'> & {
|
|
90
89
|
cwd?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{C as e}from"./sdk-contracts.js";import{r as t}from"./sdk-batch-runner.js";import{n}from"./app-inventory.js";import"./device.js";import{t as r}from"./request-cancellation.js";import{n as i,t as a}from"./ios-client.js";import{a as o,i as s}from"./snapshot.js";import c from"node:path";import l from"node:fs";import u from"node:os";import{setTimeout as d}from"node:timers/promises";function f(e){return e?.trim()||void 0}async function p(e,t){let n=await i({apiUrl:e.apiUrl,adbUrl:e.adbUrl,token:e.token,logLevel:`warn`}),r={platform:`android`,lease:e.lease,instanceId:e.instanceId,device:e.device,client:n,dependencies:t},a={exec:async(e,t)=>await y(r,e,t),text:async e=>{await n.setText(e.target,e.text)}};return a.reverse=await t.android.createPortReverse(a.exec),Object.assign(r,{adbProvider:a})}function m(e){return e.dependencies.android.createInteractor(e.device,e.adbProvider)}async function h(e,t,n,i,a,o){a?.throwIfAborted();let s=f(i?.packageNameHint);i?.relaunch&&s&&await y(t,[`shell`,`am`,`force-stop`,s],{allowFailure:!0,signal:a});let c=await r(o,e.assets.getOrUpload({path:n,name:T(s,n)},{signal:a}),a);await r(o,t.client.sendAsset(c.signedDownloadUrl),a),a?.throwIfAborted();let l=s?await t.dependencies.android.inferAppName(s):void 0;return{...s?{packageName:s,launchTarget:s}:{},...l?{appName:l}:{}}}async function g(e,t){await e.adbProvider.reverse?.ensure({local:w(t.devicePort),remote:w(t.hostPort),ownerId:t.name})}async function _(e){await e.adbTunnelPromise?.catch(()=>{});let t=e.adbSerial;t&&(await v(e),await e.dependencies.host.runAdb([`disconnect`,t],{allowFailure:!0,timeoutMs:1e4}).catch(()=>{})),e.adbTunnel?.close(),e.adbTunnel=void 0,e.adbSerial=void 0,e.adbTunnelPromise=void 0}async function v(e){let t=e.adbProvider.reverse;if(!t?.list)return;let n=await t.list().catch(()=>[]),r=new Set,i=[];for(let e of n)e.ownerId?r.add(e.ownerId):i.push(e.local);await Promise.allSettled([...[...r].map(async e=>await t.removeAllOwned(e)),...i.map(async e=>await t.remove(e))])}async function y(e,t,n){let{adbArgs:r,result:i}=await b(e,t,n);return await x(r,i,n?.allowFailure,e.dependencies)}async function b(e,t,n){let r=[`-s`,await S(e),...t];return{adbArgs:r,result:await e.dependencies.host.runAdb(r,{allowFailure:n?.allowFailure,binaryStdout:n?.binaryStdout,stdin:n?.stdin,timeoutMs:n?.timeoutMs??3e4,signal:n?.signal})}}async function x(e,t,n,r){if(t.exitCode!==0&&n!==!0)throw await r.android.adbError(`Limrun Android ADB command failed`,t,{command:[`adb`,...e].join(` `)});return t}async function S(e){if(e.adbSerial)return e.adbSerial;let t=e.adbTunnelPromise??C(e);e.adbTunnelPromise=t;try{return await t}catch(n){throw e.adbTunnelPromise===t&&(e.adbTunnelPromise=void 0),n}}async function C(e){let t=await e.client.startAdbTunnel(),n=`${t.address.address}:${t.address.port}`;return e.adbTunnel=t,e.adbSerial=n,n}function w(t){if(!Number.isInteger(t)||t<1||t>65535)throw new e(`INVALID_ARGS`,`Invalid Android tcp reverse port: ${t}`);return`tcp:${t}`}function T(e,t){let n=c.extname(t)||`.apk`;return`${e?.replaceAll(/[^a-zA-Z0-9_.-]+/g,`-`)||`android-app`}${n}`}async function E(e,t){let n=await a({apiUrl:e.apiUrl,token:e.token,logLevel:`warn`});return{platform:`ios`,lease:e.lease,instanceId:e.instanceId,device:e.device,client:n,dependencies:t}}async function D(e,t,n,i,a,o){a?.throwIfAborted();let s=await j(n,t.dependencies);try{a?.throwIfAborted();let n=await r(o,e.assets.getOrUpload({path:s.uploadPath,name:s.assetName},{signal:a}),a),c=(await O(t,n.signedDownloadUrl,{md5:n.md5,relaunch:i?.relaunch,appIdentifierHint:i?.appIdentifierHint},a,o)).appId;return{...c?{bundleId:c,launchTarget:c}:{},...s.appName?{appName:s.appName}:{}}}finally{await s.cleanup()}}async function O(t,n,i,a,o){a?.throwIfAborted();let s=await r(o,t.client.listApps(),a).catch(e=>{if(a?.aborted)throw e}),c=f((await r(o,t.client.installApp(n,{md5:i?.md5,launchMode:i?.relaunch?`RelaunchIfRunning`:`ForegroundIfRunning`}),a)).bundleId),l=f(i?.appIdentifierHint),u=[];for(let e of N){e>0&&await d(e,void 0,{signal:a}),u=await r(o,t.client.listApps(),a);let n=P({resultBundleId:c,requestedBundleId:l,beforeInstallApps:s,afterInstallApps:u});if(n)return{appId:n}}throw new e(`COMMAND_FAILED`,`Limrun iOS app installation could not be verified.`,{resultBundleId:c,requestedBundleId:l,installedUserApps:u.filter(I).map(e=>e.bundleId).sort()})}function k(e){return new A(e)}var A=class{session;constructor(e){this.session=e}async open(e,n){if(n?.url){await this.session.client.launchApp(await this.session.dependencies.ios.resolveAppAlias(e)),await this.session.client.openUrl(n.url);return}if(t(e)){await this.session.client.openUrl(e);return}await this.session.client.launchApp(await this.session.dependencies.ios.resolveAppAlias(e))}async openDevice(){}async close(e){e&&await this.session.client.terminateApp(await this.session.dependencies.ios.resolveAppAlias(e)).catch(()=>{})}async tap(e,t){await this.session.client.tap(e,t)}async tapElementSelector(e){await this.session.client.tapElement(s(e))}async doubleTap(e,t){await this.tap(e,t),await this.tap(e,t)}async longPress(){throw R(`longpress`,`Limrun iOS direct sessions do not expose long press yet.`)}async focus(e,t){await this.tap(e,t)}async type(e,t){await this.enterText(e,t)}async fill(e,t,n,r){let{awaitLimrunTextEntryFocus:i,readLimrunUnambiguousTapTargets:a,readLimrunTextEntryFocus:o}=await import(`./text-entry-focus.js`),s=a(await this.session.client.elementTree(),e,t);await this.tap(e,t);let c=await i({targetsAtPoint:s,readFocus:async()=>o(await this.session.client.elementTree()),sleep:e=>d(e),x:e,y:t});return await this.session.client.pressKey(`a`,[`command`]),n.length===0?(await this.session.client.pressKey(`delete`),{textEntryReadiness:c}):(await this.enterText(n,r),{textEntryReadiness:c})}async enterText(e,t){if(t&&t>0){for(let n of Array.from(e))await this.session.client.typeText(n,!1,{requireFocus:!1}),await d(t);return}await this.session.client.typeText(e,!1,{requireFocus:!1})}async scroll(e,t){await this.session.client.scroll(e,t?.pixels??300)}async screenshot(e){let t=await this.session.client.screenshot();await o(e,t.base64)}async snapshot(){let{captureLimrunIosSnapshot:e}=await import(`./ios-snapshot-adapter.js`);return await e(this.session)}async back(){await this.session.client.pressKey(`escape`)}async home(){throw R(`home`,`Limrun iOS direct sessions do not expose home yet.`)}async setOrientation(e){if(e===`portrait-upside-down`)throw R(`orientation`,`Limrun iOS direct sessions support portrait and landscape orientation, not portrait upside-down.`);await this.session.client.setOrientation(e===`portrait`?`Portrait`:`Landscape`)}async performGesture(){throw R(`gesture`,`Limrun iOS direct sessions do not expose portable gesture execution yet.`)}async appSwitcher(){throw R(`app-switcher`,`Limrun iOS direct sessions do not expose app switcher yet.`)}async tvRemote(){throw R(`tv-remote`,`Limrun iOS direct sessions do not expose tv remote control.`)}async readAlert(){throw R(`alert`,L)}async awaitAlert(){throw R(`alert`,L)}async acceptAlert(){throw R(`alert`,L)}async dismissAlert(){throw R(`alert`,L)}async readClipboard(){throw R(`clipboard`,`Limrun iOS direct sessions do not expose clipboard read yet.`)}async writeClipboard(){throw R(`clipboard`,`Limrun iOS direct sessions do not expose clipboard write yet.`)}async setSetting(){throw R(`settings`,`Limrun iOS direct sessions do not expose settings changes yet.`)}};async function j(e,t){if(!(await l.promises.stat(e)).isDirectory())return{uploadPath:e,assetName:c.basename(e),appName:M(e),cleanup:async()=>{}};let n=await l.promises.mkdtemp(c.join(u.tmpdir(),`agent-device-limrun-ios-app-`)),r=c.join(n,`${c.basename(e)}.zip`);try{await t.host.archiveDirectory({sourceDirectory:c.dirname(e),entryName:c.basename(e),archivePath:r})}catch(e){throw await l.promises.rm(n,{recursive:!0,force:!0}),e}return{uploadPath:r,assetName:c.basename(r),appName:await t.ios.readBundleAppName(e)??M(e),cleanup:async()=>{await l.promises.rm(n,{recursive:!0,force:!0})}}}function M(e){return c.basename(e).replace(/\.(?:app|ipa|apk|aab|zip)$/i,``)||void 0}const N=[0,250];function P(e){let t=new Set(e.afterInstallApps.map(e=>e.bundleId));return(e.resultBundleId&&t.has(e.resultBundleId)?e.resultBundleId:void 0)??(e.requestedBundleId&&t.has(e.requestedBundleId)?e.requestedBundleId:void 0)??F(e.beforeInstallApps,e.afterInstallApps)}function F(e,t){if(!e)return;let n=new Set(e.map(e=>e.bundleId)),r=t.filter(e=>I(e)&&!n.has(e.bundleId));return r.length===1?r[0]?.bundleId:void 0}function I(e){return!e.bundleId.startsWith(`com.apple.`)&&!e.installType.toLowerCase().includes(`system`)}const L=`Limrun iOS direct sessions do not expose alert inspection yet.`;function R(t,n){throw new e(`UNSUPPORTED_OPERATION`,n,{command:t})}function z(e){return e.platform===`android`?B(e):V(e)}function B(e){let t=e.adbProvider.exec;return{platform:`android`,device:e.device,interactor:m(e),adb:e.adbProvider,listApps:async r=>await e.dependencies.android.listApps(t,n(r)),getForegroundApp:async n=>await e.dependencies.android.getForegroundApp(e.device,t,n),pressKey:async(t,n)=>{await e.client.pressKey(t,n)},getKeyboardState:async()=>await e.dependencies.android.getKeyboardState(t),dismissKeyboard:async()=>await e.dependencies.android.dismissKeyboard(t),readLogs:async n=>await e.dependencies.android.readLogs(t,n),...H(e.client),installRemoteApp:async t=>{await e.client.sendAsset(t)}}}function V(e){return{platform:`ios`,device:e.device,interactor:k(e),viewport:{width:e.client.deviceInfo.screenWidth,height:e.client.deviceInfo.screenHeight},listApps:async t=>(await e.client.listApps()).filter(e=>n(t)===`all`||I(e)).map(e=>({id:e.bundleId,name:e.name,installType:e.installType})).sort((e,t)=>e.id.localeCompare(t.id)),pressKey:async(t,n)=>{await e.client.pressKey(t,n)},readLogs:async(t,n)=>await e.client.appLogTail(t,n),...H(e.client),installRemoteApp:async(t,n)=>await O(e,t,n),runSimctl:t=>e.client.simctl(t)}}function H(e){return{startRecording:async t=>{await e.startRecording(t)},stopRecording:async({outPath:t})=>await e.stopRecording({localPath:t})}}export{_ as a,p as c,D as i,h as l,k as n,g as o,E as r,m as s,z as t};
|
|
1
|
+
import{C as e}from"./sdk-contracts.js";import{r as t}from"./sdk-batch-runner.js";import{n}from"./app-inventory.js";import"./device.js";import{t as r}from"./request-cancellation.js";import{n as i,t as a}from"./ios-client.js";import{a as o,i as s}from"./snapshot.js";import c from"node:path";import l from"node:fs";import u from"node:os";import{setTimeout as d}from"node:timers/promises";function f(e){return e?.trim()||void 0}async function p(e,t){let n=await i({apiUrl:e.apiUrl,adbUrl:e.adbUrl,token:e.token,logLevel:`warn`}),r={platform:`android`,lease:e.lease,instanceId:e.instanceId,device:e.device,client:n,dependencies:t},a={exec:async(e,t)=>await y(r,e,t),text:async e=>{await n.setText(e.target,e.text)}};return a.reverse=await t.android.createPortReverse(a.exec),Object.assign(r,{adbProvider:a})}function m(e){return e.dependencies.android.createInteractor(e.device,e.adbProvider)}async function h(e,t,n,i,a,o){a?.throwIfAborted();let s=f(i?.packageNameHint);i?.relaunch&&s&&await y(t,[`shell`,`am`,`force-stop`,s],{allowFailure:!0,signal:a});let c=await r(o,e.assets.getOrUpload({path:n,name:T(s,n)},{signal:a}),a);await r(o,t.client.sendAsset(c.signedDownloadUrl),a),a?.throwIfAborted();let l=s?await t.dependencies.android.inferAppName(s):void 0;return{...s?{packageName:s,launchTarget:s}:{},...l?{appName:l}:{}}}async function g(e,t){await e.adbProvider.reverse?.ensure({local:w(t.devicePort),remote:w(t.hostPort),ownerId:t.name})}async function _(e){await e.adbTunnelPromise?.catch(()=>{});let t=e.adbSerial;t&&(await v(e),await e.dependencies.host.runAdb(e.dependencies.android.hostAdbInvocation([`disconnect`,t]),{allowFailure:!0,timeoutMs:1e4}).catch(()=>{})),e.adbTunnel?.close(),e.adbTunnel=void 0,e.adbSerial=void 0,e.adbTunnelPromise=void 0}async function v(e){let t=e.adbProvider.reverse;if(!t?.list)return;let n=await t.list().catch(()=>[]),r=new Set,i=[];for(let e of n)e.ownerId?r.add(e.ownerId):i.push(e.local);await Promise.allSettled([...[...r].map(async e=>await t.removeAllOwned(e)),...i.map(async e=>await t.remove(e))])}async function y(e,t,n){let{invocation:r,result:i}=await b(e,t,n);return await x(r,i,n?.allowFailure,e.dependencies)}async function b(e,t,n){let r=await S(e),i=e.dependencies.android.deviceAdbInvocation(r,t);return{invocation:i,result:await e.dependencies.host.runAdb(i,{allowFailure:n?.allowFailure,binaryStdout:n?.binaryStdout,stdin:n?.stdin,timeoutMs:n?.timeoutMs??3e4,signal:n?.signal})}}async function x(e,t,n,r){if(t.exitCode!==0&&n!==!0)throw await r.android.adbError(`Limrun Android ADB command failed`,t,e);return t}async function S(e){if(e.adbSerial)return e.adbSerial;let t=e.adbTunnelPromise??C(e);e.adbTunnelPromise=t;try{return await t}catch(n){throw e.adbTunnelPromise===t&&(e.adbTunnelPromise=void 0),n}}async function C(e){let t=await e.client.startAdbTunnel(),n=`${t.address.address}:${t.address.port}`;return e.adbTunnel=t,e.adbSerial=n,n}function w(t){if(!Number.isInteger(t)||t<1||t>65535)throw new e(`INVALID_ARGS`,`Invalid Android tcp reverse port: ${t}`);return`tcp:${t}`}function T(e,t){let n=c.extname(t)||`.apk`;return`${e?.replaceAll(/[^a-zA-Z0-9_.-]+/g,`-`)||`android-app`}${n}`}async function E(e,t){let n=await a({apiUrl:e.apiUrl,token:e.token,logLevel:`warn`});return{platform:`ios`,lease:e.lease,instanceId:e.instanceId,device:e.device,client:n,dependencies:t}}async function D(e,t,n,i,a,o){a?.throwIfAborted();let s=await j(n,t.dependencies);try{a?.throwIfAborted();let n=await r(o,e.assets.getOrUpload({path:s.uploadPath,name:s.assetName},{signal:a}),a),c=(await O(t,n.signedDownloadUrl,{md5:n.md5,relaunch:i?.relaunch,appIdentifierHint:i?.appIdentifierHint},a,o)).appId;return{...c?{bundleId:c,launchTarget:c}:{},...s.appName?{appName:s.appName}:{}}}finally{await s.cleanup()}}async function O(t,n,i,a,o){a?.throwIfAborted();let s=await r(o,t.client.listApps(),a).catch(e=>{if(a?.aborted)throw e}),c=f((await r(o,t.client.installApp(n,{md5:i?.md5,launchMode:i?.relaunch?`RelaunchIfRunning`:`ForegroundIfRunning`}),a)).bundleId),l=f(i?.appIdentifierHint),u=[];for(let e of N){e>0&&await d(e,void 0,{signal:a}),u=await r(o,t.client.listApps(),a);let n=I({resultBundleId:c,requestedBundleId:l,beforeInstallApps:s,afterInstallApps:u});if(n)return{appId:n}}throw new e(`COMMAND_FAILED`,`Limrun iOS app installation could not be verified.`,{resultBundleId:c,requestedBundleId:l,installedUserApps:u.filter(R).map(e=>e.bundleId).sort()})}function k(e){return new A(e)}var A=class{session;constructor(e){this.session=e}async open(e,n){if(n?.url){await this.session.client.launchApp(await this.session.dependencies.ios.resolveAppAlias(e)),await this.session.client.openUrl(n.url);return}if(t(e)){await this.session.client.openUrl(e);return}await this.session.client.launchApp(await this.session.dependencies.ios.resolveAppAlias(e))}async openDevice(){}async close(e){e&&await this.session.client.terminateApp(await this.session.dependencies.ios.resolveAppAlias(e)).catch(()=>{})}async tap(e,t){await this.session.client.tap(e,t)}async tapElementSelector(e){await this.session.client.tapElement(s(e))}async doubleTap(e,t){await this.session.client.performActions([{type:`tap`,x:e,y:t},{type:`wait`,durationMs:F},{type:`tap`,x:e,y:t}])}async longPress(e,t,n=P){await this.session.client.performActions([{type:`touchDown`,x:e,y:t},{type:`wait`,durationMs:n},{type:`touchUp`,x:e,y:t}])}async focus(e,t){await this.tap(e,t)}async type(e,t){await this.enterText(e,t)}async fill(e,t,n,r){let{awaitLimrunTextEntryFocus:i,readLimrunUnambiguousTapTargets:a,readLimrunTextEntryFocus:o}=await import(`./text-entry-focus.js`),s=a(await this.session.client.elementTree(),e,t);await this.tap(e,t);let c=await i({targetsAtPoint:s,readFocus:async()=>o(await this.session.client.elementTree()),sleep:e=>d(e),x:e,y:t});return await this.session.client.pressKey(`a`,[`command`]),n.length===0?(await this.session.client.pressKey(`delete`),{textEntryReadiness:c}):(await this.enterText(n,r),{textEntryReadiness:c})}async enterText(e,t){if(t&&t>0){for(let n of Array.from(e))await this.session.client.typeText(n,!1,{requireFocus:!1}),await d(t);return}await this.session.client.typeText(e,!1,{requireFocus:!1})}async scroll(e,t){await this.session.client.scroll(e,t?.pixels??300)}async screenshot(e){let t=await this.session.client.screenshot();await o(e,t.base64)}async snapshot(){let{captureLimrunIosSnapshot:e}=await import(`./ios-snapshot-adapter.js`);return await e(this.session)}async back(){await this.session.client.pressKey(`escape`)}async home(){throw B(`home`,`Limrun iOS direct sessions do not expose home yet.`)}async setOrientation(e){if(e===`portrait-upside-down`)throw B(`orientation`,`Limrun iOS direct sessions support portrait and landscape orientation, not portrait upside-down.`);await this.session.client.setOrientation(e===`portrait`?`Portrait`:`Landscape`)}async performGesture(){throw B(`gesture`,`Limrun iOS direct sessions do not expose portable gesture execution yet.`)}async appSwitcher(){throw B(`app-switcher`,`Limrun iOS direct sessions do not expose app switcher yet.`)}async tvRemote(){throw B(`tv-remote`,`Limrun iOS direct sessions do not expose tv remote control.`)}async readAlert(){throw B(`alert`,z)}async awaitAlert(){throw B(`alert`,z)}async acceptAlert(){throw B(`alert`,z)}async dismissAlert(){throw B(`alert`,z)}async readClipboard(){throw B(`clipboard`,`Limrun iOS direct sessions do not expose clipboard read yet.`)}async writeClipboard(){throw B(`clipboard`,`Limrun iOS direct sessions do not expose clipboard write yet.`)}async setSetting(){throw B(`settings`,`Limrun iOS direct sessions do not expose settings changes yet.`)}};async function j(e,t){if(!(await l.promises.stat(e)).isDirectory())return{uploadPath:e,assetName:c.basename(e),appName:M(e),cleanup:async()=>{}};let n=await l.promises.mkdtemp(c.join(u.tmpdir(),`agent-device-limrun-ios-app-`)),r=c.join(n,`${c.basename(e)}.zip`);try{await t.host.archiveDirectory({sourceDirectory:c.dirname(e),entryName:c.basename(e),archivePath:r})}catch(e){throw await l.promises.rm(n,{recursive:!0,force:!0}),e}return{uploadPath:r,assetName:c.basename(r),appName:await t.ios.readBundleAppName(e)??M(e),cleanup:async()=>{await l.promises.rm(n,{recursive:!0,force:!0})}}}function M(e){return c.basename(e).replace(/\.(?:app|ipa|apk|aab|zip)$/i,``)||void 0}const N=[0,250],P=800,F=80;function I(e){let t=new Set(e.afterInstallApps.map(e=>e.bundleId));return(e.resultBundleId&&t.has(e.resultBundleId)?e.resultBundleId:void 0)??(e.requestedBundleId&&t.has(e.requestedBundleId)?e.requestedBundleId:void 0)??L(e.beforeInstallApps,e.afterInstallApps)}function L(e,t){if(!e)return;let n=new Set(e.map(e=>e.bundleId)),r=t.filter(e=>R(e)&&!n.has(e.bundleId));return r.length===1?r[0]?.bundleId:void 0}function R(e){return!e.bundleId.startsWith(`com.apple.`)&&!e.installType.toLowerCase().includes(`system`)}const z=`Limrun iOS direct sessions do not expose alert inspection yet.`;function B(t,n){throw new e(`UNSUPPORTED_OPERATION`,n,{command:t})}function V(e){return e.platform===`android`?H(e):U(e)}function H(e){let t=e.adbProvider.exec;return{platform:`android`,device:e.device,interactor:m(e),adb:e.adbProvider,listApps:async r=>await e.dependencies.android.listApps(t,n(r)),getForegroundApp:async n=>await e.dependencies.android.getForegroundApp(e.device,t,n),pressKey:async(t,n)=>{await e.client.pressKey(t,n)},getKeyboardState:async()=>await e.dependencies.android.getKeyboardState(t),dismissKeyboard:async()=>await e.dependencies.android.dismissKeyboard(t),readLogs:async n=>await e.dependencies.android.readLogs(t,n),...W(e.client),installRemoteApp:async t=>{await e.client.sendAsset(t)}}}function U(e){return{platform:`ios`,device:e.device,interactor:k(e),viewport:{width:e.client.deviceInfo.screenWidth,height:e.client.deviceInfo.screenHeight},listApps:async t=>(await e.client.listApps()).filter(e=>n(t)===`all`||R(e)).map(e=>({id:e.bundleId,name:e.name,installType:e.installType})).sort((e,t)=>e.id.localeCompare(t.id)),pressKey:async(t,n)=>{await e.client.pressKey(t,n)},readLogs:async(t,n)=>await e.client.appLogTail(t,n),...W(e.client),installRemoteApp:async(t,n)=>await O(e,t,n),runSimctl:t=>e.client.simctl(t)}}function W(e){return{startRecording:async t=>{await e.startRecording(t)},stopRecording:async({outPath:t})=>await e.stopRecording({localPath:t})}}export{_ as a,p as c,D as i,h as l,k as n,g as o,E as r,m as s,V as t};
|