agent-device 0.20.8 → 0.20.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +94 -31
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.8.apk → agent-device-android-ime-helper-0.20.10.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.10.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.8.manifest.json → agent-device-android-ime-helper-0.20.10.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.8.apk → agent-device-android-snapshot-helper-0.20.10.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.10.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.8.manifest.json → agent-device-android-snapshot-helper-0.20.10.manifest.json} +6 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +3 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +13 -7
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +10 -117
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +4 -4
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+FlatSnapshotFiltering.swift +103 -2
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift +22 -23
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +3 -23
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Navigation.swift +10 -11
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift +108 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +8 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift +179 -73
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +13 -12
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentation.swift +183 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentationTests.swift +0 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SystemModal.swift +20 -18
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextInputCandidatePolicy.swift +19 -0
- package/dist/src/agent-browser-tool.js +1 -1
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/ai-sdk.d.ts +61 -0
- package/dist/src/ai-sdk.js +1 -0
- package/dist/src/android-adb.d.ts +6 -6
- 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 +6 -7
- package/dist/src/app-lifecycle2.js +2 -2
- package/dist/src/app-log-reconnect.js +1 -1
- package/dist/src/app-log-runtime.js +3 -3
- package/dist/src/app-resolution.js +2 -2
- package/dist/src/app-state.js +2 -0
- package/dist/src/appearance.js +1 -0
- package/dist/src/apps.js +5 -5
- package/dist/src/artifacts.d.ts +1 -1
- package/dist/src/audio-probe.js +1 -1
- package/dist/src/auth-session.js +1 -1
- package/dist/src/backend-snapshot-options.js +1 -0
- package/dist/src/boot-diagnostics.js +2 -2
- package/dist/src/bounds.js +1 -0
- package/dist/src/byte-limit-stream.js +1 -0
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +42 -30
- package/dist/src/cli-runner.js +1 -1
- package/dist/src/cli.js +7 -7
- package/dist/src/client-metro.js +1 -1
- package/dist/src/client-types.d.ts +1582 -0
- package/dist/src/command-catalog.js +1 -0
- package/dist/src/command-metadata.js +1 -1
- package/dist/src/command-schema.js +1 -1
- package/dist/src/command-surface.js +1 -1
- package/dist/src/command-tools.js +2 -0
- package/dist/src/config.js +1 -0
- package/dist/src/connection-runtime.js +1 -1
- package/dist/src/connection.js +3 -3
- package/dist/src/contracts.d.ts +1 -1
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon-shutdown-report.js +1 -1
- package/dist/src/daemon.js +1 -1
- package/dist/src/debug-symbols.js +3 -3
- package/dist/src/device-claim-inspection.js +1 -1
- package/dist/src/device-input-state.js +1 -1
- package/dist/src/device-ready.js +1 -1
- package/dist/src/device2.js +2 -2
- package/dist/src/dispatch.js +1 -1
- package/dist/src/entities.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/generic-settle.js +1 -1
- package/dist/src/generic.js +1 -1
- package/dist/src/harmonyos.js +1 -1
- package/dist/src/hdc.js +1 -1
- package/dist/src/helper-package-install.js +1 -0
- package/dist/src/helper.js +2 -2
- package/dist/src/host-process.js +1 -1
- package/dist/src/ime-lifecycle.js +2 -9
- package/dist/src/ime-recovery-marker.js +1 -0
- package/dist/src/index.d.ts +2 -1569
- package/dist/src/index.js +1 -1
- package/dist/src/input-actions.js +4 -4
- package/dist/src/input-actions2.js +1 -1
- package/dist/src/install-artifact.js +1 -1
- package/dist/src/install-artifact2.js +1 -1
- package/dist/src/install-source2.js +1 -1
- package/dist/src/interaction-common.js +1 -0
- package/dist/src/interaction-runtime.js +1 -1
- package/dist/src/interaction-snapshot.js +1 -1
- package/dist/src/interaction.js +1 -1
- package/dist/src/interaction2.js +1 -0
- package/dist/src/interactor.js +2 -2
- package/dist/src/interactor2.js +1 -1
- package/dist/src/interactors.js +1 -0
- package/dist/src/internal/bin.js +2 -2
- package/dist/src/internal/daemon.js +4 -7
- package/dist/src/internal/png-worker.js +1 -1
- package/dist/src/inventory.js +1 -1
- package/dist/src/keyed-lock.js +1 -0
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun-runtime-dependencies.js +1 -1
- package/dist/src/limrun.d.ts +13 -3
- package/dist/src/limrun.js +1 -1
- package/dist/src/linux.js +1 -1
- package/dist/src/location-coordinates.js +1 -0
- package/dist/src/logcat.js +1 -1
- package/dist/src/manifest.js +1 -1
- package/dist/src/mobile-snapshot-semantics.js +1 -0
- package/dist/src/observability.js +1 -0
- package/dist/src/owner-identity.js +1 -1
- package/dist/src/perf.js +4 -0
- package/dist/src/physical-device-control.js +1 -1
- package/dist/src/platform-runtime-app-log-process.js +1 -1
- package/dist/src/platform-runtime-host.js +1 -1
- package/dist/src/platform-runtime-network-web-transport.js +1 -1
- package/dist/src/platform-runtime-open-target.js +1 -0
- package/dist/src/platform-runtime-operation-host.js +4 -4
- package/dist/src/platform-runtime-runtime-hints.js +2 -0
- package/dist/src/platform-runtime-screen-recording-apple-runner-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-runner-transport.js +1 -1
- package/dist/src/platform-runtime-screen-recording-apple-transport.js +1 -1
- package/dist/src/platform-runtime-screen-recording-finalizer-host.js +1 -1
- package/dist/src/platform-runtime-screen-recording-web-host.js +1 -1
- package/dist/src/platform-runtime.js +1 -1
- package/dist/src/platform-runtime2.js +1 -0
- package/dist/src/plist.js +1 -1
- package/dist/src/png-resize.js +1 -0
- package/dist/src/png-worker-contract.js +1 -1
- package/dist/src/process-lock.js +1 -1
- package/dist/src/project-runtime.js +1 -0
- package/dist/src/provider-webdriver.js +1 -1
- package/dist/src/provider.js +1 -0
- package/dist/src/proxy.js +1 -1
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-runtime.js +1 -1
- package/dist/src/record-trace.js +1 -1
- package/dist/src/recording-export-quality.js +1 -0
- package/dist/src/registry.js +29 -26
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/replay.js +2 -2
- package/dist/src/reporting.js +5 -5
- package/dist/src/rolldown-runtime.js +1 -0
- package/dist/src/runner-client.js +1 -0
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-lease.js +1 -1
- package/dist/src/runner-sequence.js +1 -1
- package/dist/src/runtime-transport.js +1 -1
- package/dist/src/runtime.js +3 -3
- package/dist/src/runtime2.js +4 -3
- package/dist/src/runtime3.js +1 -3
- package/dist/src/runtime4.js +3 -1
- package/dist/src/runtime5.js +1 -1
- package/dist/src/runtime6.js +1 -1
- package/dist/src/runtime7.js +1 -1
- package/dist/src/runtime8.js +1 -0
- package/dist/src/runtime9.js +1 -0
- package/dist/src/scoped-provider.js +1 -0
- package/dist/src/screenshot-density.js +1 -0
- package/dist/src/screenshot-result.js +4 -4
- package/dist/src/screenshot.js +1 -1
- package/dist/src/script-source-bundle.js +16 -0
- package/dist/src/sdk-android-adb.d.ts +44 -26
- package/dist/src/sdk-android-adb.js +4 -4
- package/dist/src/sdk-batch-runner.js +3 -3
- package/dist/src/sdk-contracts.d.ts +125 -88
- package/dist/src/sdk-contracts.js +2 -2
- package/dist/src/sdk-device.js +1 -1
- package/dist/src/sdk-finders.d.ts +1 -1
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/sdk-io.js +1 -1
- package/dist/src/sdk-remote-config.js +1 -1
- package/dist/src/sdk-selectors.d.ts +107 -95
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/sdk.js +1 -0
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selectors.d.ts +1 -1
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +10 -3
- package/dist/src/session-target-evidence.js +1 -1
- package/dist/src/session.js +1 -30
- package/dist/src/session2.js +27 -0
- package/dist/src/setting-state.js +1 -1
- package/dist/src/shared.js +1 -1
- package/dist/src/simctl.js +1 -0
- package/dist/src/simulator-state.js +1 -0
- package/dist/src/simulator.js +1 -1
- package/dist/src/snapshot-runtime.js +1 -1
- package/dist/src/snapshot-scope.js +1 -0
- package/dist/src/snapshot-session.js +1 -1
- package/dist/src/snapshot.js +8 -1
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/snapshot3.js +1 -0
- package/dist/src/src.js +1 -1
- package/dist/src/src2.js +1 -2
- package/dist/src/src3.js +2 -1
- package/dist/src/src4.js +1 -0
- package/dist/src/string-enum.js +1 -0
- package/dist/src/tool-provider.js +3 -3
- package/dist/src/tool-provider2.js +1 -1
- package/dist/src/tool-provider3.js +1 -1
- package/dist/src/update-check.js +1 -1
- package/dist/src/verdict.js +1 -0
- package/dist/src/verified-file.js +1 -0
- package/dist/src/version.js +1 -1
- package/dist/src/video.js +1 -1
- package/dist/src/web.js +1 -1
- package/package.json +27 -10
- package/server.json +3 -3
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.8.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.8.apk.sha256 +0 -1
- package/dist/src/interaction-touch-reference-frame.js +0 -1
- package/dist/src/notifications.js +0 -1
- package/dist/src/platform-runtime-toolchain-host.js +0 -1
- package/dist/src/prepare-kind.js +0 -15
- package/dist/src/selector-vocabulary.js +0 -1
- package/dist/src/text-surface.js +0 -1
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { H as PlatformSelector } from "./sdk-contracts.js";
|
|
2
|
+
import { t as AgentDeviceClient } from "./client-types.js";
|
|
3
|
+
import { ToolApprovalStatus, ToolSet } from "ai";
|
|
4
|
+
//#region src/ai-sdk/index.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* `'core'` — the curated perceive/act loop (see the `frameworkTier` pinning
|
|
7
|
+
* test in `src/core/command-descriptor/__tests__/parity.test.ts`). `'all'`
|
|
8
|
+
* exposes every MCP-exposed command, same set the MCP server surfaces.
|
|
9
|
+
*/
|
|
10
|
+
type AgentDeviceToolSet = 'core' | 'all';
|
|
11
|
+
type CreateAgentDeviceToolsOptions = {
|
|
12
|
+
/**
|
|
13
|
+
* The agent-device session every tool call targets. Required: pinning one
|
|
14
|
+
* session here is what lets the model call these tools without ever seeing
|
|
15
|
+
* (or being able to typo) a session name — mirroring the "keep the client
|
|
16
|
+
* outside tool execution so calls share one named session" guidance in the
|
|
17
|
+
* AI SDK doc.
|
|
18
|
+
*/
|
|
19
|
+
session: string;
|
|
20
|
+
/**
|
|
21
|
+
* When set, pins every tool call to this platform the same way `session` is
|
|
22
|
+
* pinned, and removes `platform` from the tools' input schemas. Omit it to
|
|
23
|
+
* let each call (and the daemon's own default-device selection) decide.
|
|
24
|
+
*/
|
|
25
|
+
platform?: PlatformSelector;
|
|
26
|
+
/** Which tools to build. Defaults to `'core'`. */
|
|
27
|
+
set?: AgentDeviceToolSet;
|
|
28
|
+
/**
|
|
29
|
+
* Per-command approval policy, keyed by command name (e.g. `install`,
|
|
30
|
+
* `close`). Returned as `toolApproval`, ready to pass straight to
|
|
31
|
+
* `ToolLoopAgent`/`generateText`/`streamText` — see
|
|
32
|
+
* https://ai-sdk.dev/docs/agents/tool-approvals. `tool()`'s own
|
|
33
|
+
* `needsApproval` option is deprecated in favor of this, so this factory
|
|
34
|
+
* never sets it.
|
|
35
|
+
*/
|
|
36
|
+
approval?: Partial<Record<string, ToolApprovalStatus>>;
|
|
37
|
+
};
|
|
38
|
+
type AgentDeviceTools = {
|
|
39
|
+
tools: ToolSet;
|
|
40
|
+
client: AgentDeviceClient;
|
|
41
|
+
toolApproval?: Partial<Record<string, ToolApprovalStatus>>;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Builds an AI SDK tool set from the same command registry the MCP server
|
|
45
|
+
* exposes (`listCommandTools()` / `createCommandToolExecutor()`), so the two
|
|
46
|
+
* integrations stay in lockstep without a hand-maintained tool list. Uses
|
|
47
|
+
* `jsonSchema()` against the registry's JSON Schema directly — no zod layer.
|
|
48
|
+
*
|
|
49
|
+
* `ai` is an optional peer dependency, so it is imported lazily here rather
|
|
50
|
+
* than at module scope: importing `agent-device/ai-sdk` itself never
|
|
51
|
+
* requires `ai` to be installed, only calling this function does.
|
|
52
|
+
*
|
|
53
|
+
* The returned `client` is a plain `agent-device` client for the same
|
|
54
|
+
* session, for the host's own setup/teardown (e.g. `client.apps.open(...)`
|
|
55
|
+
* before the loop, `client.sessions.close()` in a `finally`); the tools
|
|
56
|
+
* themselves execute through the registry's own executor, independent of
|
|
57
|
+
* this instance.
|
|
58
|
+
*/
|
|
59
|
+
declare function createAgentDeviceTools(options: CreateAgentDeviceToolsOptions): Promise<AgentDeviceTools>;
|
|
60
|
+
//#endregion
|
|
61
|
+
export { AgentDeviceToolSet, AgentDeviceTools, CreateAgentDeviceToolsOptions, createAgentDeviceTools };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{y as t}from"./sdk-batch-runner.js";import{n}from"./agent-device-client.js";import{i as r,n as i,r as a}from"./command-tools.js";const o=[`session`,`stateDir`,`mcpOutputFormat`,`includeCost`,`responseLevel`];async function s(s){let{jsonSchema:d,tool:f}=await c(),{session:p,platform:m,set:h=`core`,approval:g}=s,_=n({session:p,...m?{lockPlatform:m}:{}}),v=i(),y=new Set(o);m&&y.add(`platform`);let b={};for(let n of a())h===`core`&&t(n.name)!==`core`||(b[n.name]=f({description:n.description,inputSchema:d(l(n.inputSchema,y)),...n.outputSchema?{outputSchema:d(n.outputSchema)}:{},execute:async t=>{let i={...u(t,y),session:p,...m?{platform:m}:{}},a=await v.execute(n.name,i);if(a.isError){let t=a.structuredContent;throw new e(t.code,r(t),t.details)}return a.structuredContent??{}}}));return{tools:b,client:_,...g?{toolApproval:g}:{}}}async function c(){try{return await import(`ai`)}catch(t){throw new e(`MISSING_PEER_DEPENDENCY`,"createAgentDeviceTools() requires the optional peer dependency 'ai'. Install it with `pnpm add ai` (or npm/yarn equivalent).",void 0,t)}}function l(e,t){if(!e.properties)return e;let n=e.required?.filter(e=>!t.has(e));return{...e,properties:u(e.properties,t),...n?{required:n}:{}}}function u(e,t){let n={};for(let[r,i]of Object.entries(e))t.has(r)||(n[r]=i);return n}export{s as createAgentDeviceTools};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { a as createAndroidPortReverseManager, i as AndroidPortReverseEndpoint, n as AndroidAdbExecutorOptions, r as AndroidAdbProvider, t as AndroidAdbExecutor } from "./sdk-android-adb.js";
|
|
2
1
|
import { t as AppsFilter } from "./app-inventory.js";
|
|
2
|
+
import { a as createAndroidPortReverseManager, i as AndroidPortReverseEndpoint, n as AndroidAdbExecutorOptions, r as AndroidAdbProvider, t as AndroidAdbExecutor } from "./sdk-android-adb.js";
|
|
3
3
|
import { a as readAndroidClipboardWithAdb, i as getAndroidKeyboardStatusWithAdb, n as AndroidKeyboardState, o as writeAndroidClipboardWithAdb, r as dismissAndroidKeyboardWithAdb, t as AndroidKeyboardDismissResult } from "./device-input-state.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
type
|
|
4
|
+
//#region packages/contracts/src/app-state-runtime.d.ts
|
|
5
|
+
/** Neutral foreground identity returned by a selected platform/provider runtime. */
|
|
6
|
+
type AppStateRuntimeResult = Readonly<{
|
|
7
7
|
package?: string;
|
|
8
8
|
activity?: string;
|
|
9
|
-
}
|
|
9
|
+
}>;
|
|
10
10
|
//#endregion
|
|
11
11
|
//#region src/platforms/android/app-helpers.d.ts
|
|
12
12
|
type AndroidAppListFilter = AppsFilter;
|
|
@@ -19,7 +19,7 @@ declare function listAndroidAppsWithAdb(adb: AndroidAdbExecutor, options?: Andro
|
|
|
19
19
|
package: string;
|
|
20
20
|
name: string;
|
|
21
21
|
}>>;
|
|
22
|
-
declare function getAndroidAppStateWithAdb(adb: AndroidAdbExecutor): Promise<
|
|
22
|
+
declare function getAndroidAppStateWithAdb(adb: AndroidAdbExecutor): Promise<AppStateRuntimeResult>;
|
|
23
23
|
//#endregion
|
|
24
24
|
//#region src/platforms/android/app-control.d.ts
|
|
25
25
|
type AndroidOpenAppWithAdbOptions = {
|
package/dist/src/android-adb.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{r as t}from"./sdk-android-adb.js";import{
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{r as t}from"./sdk-android-adb.js";import{a as n,c as r}from"./app-lifecycle.js";import{n as i,r as a}from"./app-helpers.js";import{t as o}from"./logcat.js";import{c as s,i as c,n as l,o as u}from"./device-input-state.js";const d=`android.intent.category.LAUNCHER`,f=`android.intent.category.DEFAULT`;async function p(e,t){await e([`shell`,`am`,`force-stop`,t])}async function m(e,t,n=[d]){for(let i of n){let n=await e([`shell`,`cmd`,`package`,`resolve-activity`,`--brief`,`-a`,`android.intent.action.MAIN`,`-c`,i,t],{allowFailure:!0});if(n.exitCode!==0)continue;let a=r(n.stdout);if(a)return a}return null}async function h(t,r,i={}){let a=i.category??d;if(i.activity){await t([`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,f,`-c`,a,`-n`,g(r,i.activity)]);return}let o=await t([`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,f,`-c`,a,`-p`,r],{allowFailure:!0});if(o.exitCode===0&&!n(o.stdout,o.stderr))return;let s=await m(t,r,[a]);if(!s)throw new e(`COMMAND_FAILED`,`Failed to resolve Android launch component for ${r}`,{stdout:o.stdout,stderr:o.stderr,exitCode:o.exitCode});await t([`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,f,`-c`,a,`-n`,s])}function g(e,t){return t.includes(`/`)?t:`${e}/${t.startsWith(`.`)?t:`.${t}`}`}export{o as captureAndroidLogcatWithAdb,t as createAndroidPortReverseManager,l as dismissAndroidKeyboardWithAdb,p as forceStopAndroidAppWithAdb,i as getAndroidAppStateWithAdb,c as getAndroidKeyboardStatusWithAdb,a as listAndroidAppsWithAdb,h as openAndroidAppWithAdb,u as readAndroidClipboardWithAdb,s as writeAndroidClipboardWithAdb};
|
package/dist/src/android.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{n as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{c as n,g as r,n as i,s as a}from"./location-coordinates.js";import{F as o,n as s,u as c}from"./sdk-android-adb.js";import{t as l}from"./timeouts.js";import{f as u,g as d,n as f,o as p,s as ee}from"./app-lifecycle.js";import{a as m,s as h}from"./device-input-state.js";import{c as g,d as te,f as _,h as v,i as y,l as b,m as x,n as S,o as C,p as w,r as T,t as E,u as D}from"./input-actions.js";import{n as O}from"./snapshot.js";import{n as k,t as A}from"./setting-state.js";import{t as j}from"./appearance.js";import{t as M}from"./method-scope.js";import{promises as N}from"node:fs";const P=[`window_animation_scale`,`transition_animation_scale`,`animator_duration_scale`];async function F(e,n,r,o,s){switch(n.toLowerCase()){case`wifi`:await d(e,[`shell`,`svc`,`wifi`,A(r)?`enable`:`disable`]);return;case`airplane`:{let t=A(r),n=t?`1`:`0`,i=t?`true`:`false`;await d(e,[`shell`,`settings`,`put`,`global`,`airplane_mode_on`,n]),await d(e,[`shell`,`am`,`broadcast`,`-a`,`android.intent.action.AIRPLANE_MODE`,`--ez`,`state`,i]);return}case`location`:if(r.toLowerCase()===`set`){if(e.kind!==`emulator`)throw new t(`UNSUPPORTED_OPERATION`,`Android precise location coordinates are supported only on emulators.`,{deviceId:e.id,hint:`Use an Android emulator for adb emu geo fix, or configure location through device/provider tooling.`});let{latitude:n,longitude:r}=i(s);return await d(e,[`emu`,`geo`,`fix`,String(r),String(n)]),{latitude:n,longitude:r}}await d(e,[`shell`,`settings`,`put`,`secure`,`location_mode`,A(r)?`3`:`0`]);return;case`animations`:{let t=A(r)?`1`:`0`;for(let n of P)await d(e,[`shell`,`settings`,`put`,`global`,n,t]);return{scale:t,keys:[...P]}}case`appearance`:await d(e,[`shell`,`cmd`,`uimode`,`night`,await B(e,r)===`dark`?`yes`:`no`]);return;case`clear-app-state`:{if(r.toLowerCase()!==`clear`)throw new t(`INVALID_ARGS`,`settings clear-app-state only supports clear.`);if(!o)throw new t(`INVALID_ARGS`,`settings clear-app-state requires an app id or an active app session.`);let n=await u(e,o);if(n.type===`intent`)throw new t(`INVALID_ARGS`,`settings clear-app-state requires a package name, not an intent.`);await d(e,[`shell`,`am`,`force-stop`,n.value],{allowFailure:!0});let i=await d(e,[`shell`,`pm`,`clear`,n.value],{allowFailure:!0});if(i.exitCode!==0||!/\bSuccess\b/i.test(i.stdout))throw new t(`COMMAND_FAILED`,`Failed to clear Android app data for ${n.value}`,{package:n.value,stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode});return{package:n.value,cleared:!0}}case`fingerprint`:await L(e,I(r));return;case`permission`:{if(!o)throw new t(`INVALID_ARGS`,`permission setting requires an active app in session`);let n=a(r),i=H(s?.permissionTarget,s?.permissionMode);if(i.kind===`notifications`){await W(e,o,n,i);return}let c=n===`grant`?`grant`:`revoke`;if(i.type===`photos`){let t=await U(e,o,c);n===`reset`&&await G(e,o,t);return}await d(e,[`shell`,`pm`,c,o,i.value]),n===`reset`&&await G(e,o,i.value);return}default:throw new t(`INVALID_ARGS`,`Unsupported setting: ${n}`)}}function I(e){let n=e.trim().toLowerCase();if(n===`match`)return`match`;if(n===`nonmatch`)return`nonmatch`;throw new t(`INVALID_ARGS`,`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}async function L(e,n){let r=R(e,n),i=[];for(let t of r){let n=await d(e,t,{allowFailure:!0});if(n.exitCode===0)return;i.push({args:t,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})}let a=k(i);throw i.length>0&&i.every(e=>z(e.stdout,e.stderr))?new t(`UNSUPPORTED_OPERATION`,`Android fingerprint simulation is not supported on this target/runtime.`,{deviceId:e.id,action:n,hint:`Use an Android emulator with biometric support, or a device/runtime that exposes cmd fingerprint.`,attempts:a}):new t(`COMMAND_FAILED`,`Failed to simulate Android fingerprint.`,{deviceId:e.id,action:n,attempts:a})}function R(e,t){let n=t===`match`?`1`:`9999`,r=[[`shell`,`cmd`,`fingerprint`,`touch`,n],[`shell`,`cmd`,`fingerprint`,`finger`,n]];return e.kind===`emulator`&&r.push([`emu`,`finger`,`touch`,n]),r}function z(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`unknown command`)||n.includes(`can't find service: fingerprint`)||n.includes(`service fingerprint was not found`)||n.includes(`fingerprint cmd unavailable`)||n.includes(`emu command is not supported`)||n.includes(`emulator console is not running`)||n.includes(`fingerprint`)&&n.includes(`not found`)}async function B(e,n){let r=j(n);if(r!==`toggle`)return r;let i=await d(e,[`shell`,`cmd`,`uimode`,`night`],{allowFailure:!0});if(i.exitCode!==0)throw s(`Failed to read current Android appearance`,i);let a=V(i.stdout,i.stderr);if(!a)throw new t(`COMMAND_FAILED`,`Unable to determine current Android appearance for toggle`,{stdout:i.stdout,stderr:i.stderr});return a===`auto`?`dark`:a===`dark`?`light`:`dark`}function V(e,t){let n=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}\n${t}`);if(!n)return null;let r=n[1]?.toLowerCase();return r===`yes`?`dark`:r===`no`?`light`:r===`auto`?`auto`:null}function H(e,r){let i=n(e);if(r?.trim())throw new t(`INVALID_ARGS`,`Permission mode is only supported for photos. Received: ${r}.`);if(i===`camera`)return{kind:`pm`,value:`android.permission.CAMERA`,type:`camera`};if(i===`microphone`)return{kind:`pm`,value:`android.permission.RECORD_AUDIO`,type:`microphone`};if(i===`photos`)return{kind:`pm`,value:`android.permission.READ_MEDIA_IMAGES`,type:`photos`};if(i===`contacts`)return{kind:`pm`,value:`android.permission.READ_CONTACTS`,type:`contacts`};if(i===`notifications`)return{kind:`notifications`,appOps:`POST_NOTIFICATION`,permission:`android.permission.POST_NOTIFICATIONS`};throw new t(`INVALID_ARGS`,`Unsupported permission target on Android: ${e}. Use camera|microphone|photos|contacts|notifications.`)}async function U(e,n,r){let i=await K(e),a=i!==null&&i>=33?[`android.permission.READ_MEDIA_IMAGES`,`android.permission.READ_EXTERNAL_STORAGE`]:[`android.permission.READ_EXTERNAL_STORAGE`,`android.permission.READ_MEDIA_IMAGES`],o=[];for(let t of a){let i=await d(e,[`shell`,`pm`,r,n,t],{allowFailure:!0});if(i.exitCode===0)return t;o.push({permission:t,stderr:i.stderr,exitCode:i.exitCode})}throw new t(`COMMAND_FAILED`,`Failed to ${r} Android photos permission`,{appPackage:n,sdkInt:i,attempts:o})}async function W(e,t,n,r){let i=n===`grant`?`allow`:n===`deny`?`deny`:`default`;n===`grant`?await d(e,[`shell`,`pm`,`grant`,t,r.permission],{allowFailure:!0}):(await d(e,[`shell`,`pm`,`revoke`,t,r.permission],{allowFailure:!0}),n===`reset`&&await G(e,t,r.permission)),await d(e,[`shell`,`appops`,`set`,t,r.appOps,i])}async function G(e,t,n){await d(e,[`shell`,`pm`,`clear-permission-flags`,t,n,`user-set`],{allowFailure:!0}),await d(e,[`shell`,`pm`,`clear-permission-flags`,t,n,`user-fixed`],{allowFailure:!0})}async function K(e){let t=await d(e,[`shell`,`getprop`,`ro.build.version.sdk`],{allowFailure:!0});if(t.exitCode!==0)return null;let n=Number.parseInt(t.stdout.trim(),10);return!Number.isFinite(n)||n<=0?null:n}const q=Buffer.from([137,80,78,71,13,10,26,10]);async function J(e,t,n={}){if(n.stabilize===!1){await Z(e,t);return}await Y(e);try{await l(1e3),await Z(e,t)}finally{await X(e).catch(()=>{})}}async function Y(e){let t=t=>d(e,[`shell`,t],{allowFailure:!0});await t(`settings put global sysui_demo_allowed 1`);let n=e=>t(`am broadcast -a com.android.systemui.demo -e command ${e}`);await n(`clock -e hhmm 0941`),await n(`notifications -e visible false`)}async function X(e){await d(e,[`shell`,`am broadcast -a com.android.systemui.demo -e command exit`],{allowFailure:!0})}async function Z(e,n){let r=await d(e,[`exec-out`,`screencap`,`-p`],{binaryStdout:!0});if(!r.stdoutBuffer)throw new t(`COMMAND_FAILED`,`Failed to capture screenshot`);let i=r.stdoutBuffer.indexOf(q);if(i<0)throw new t(`COMMAND_FAILED`,`Screenshot data does not contain a valid PNG header`);let a=Q(r.stdoutBuffer,i);if(!a)throw new t(`COMMAND_FAILED`,`Screenshot data does not contain a complete PNG payload`);await N.writeFile(n,r.stdoutBuffer.subarray(i,a))}function Q(e,t){let n=t+q.length;for(;n+8<=e.length;){let t=e.readUInt32BE(n),r=n+4,i=e.toString(`ascii`,r,r+4),a=n+12+t;if(a>e.length)return null;if(i===`IEND`)return a;n=a}return null}var ne=e({createAndroidInteractor:()=>$});function $(e,t,n){let i={open:(t,n)=>p(e,t,{activity:n?.activity,appBundleId:n?.appBundleId,launchArgs:n?.launchArgs,url:n?.url}),openDevice:()=>ee(e),close:t=>f(e,t),tap:(t,n)=>b(e,t,n),doubleTap:async(t,n)=>{await b(e,t,n),await b(e,t,n)},longPress:(t,n,r)=>g(e,t,n,r),focus:(t,n)=>y(e,t,n),type:(t,n)=>w(e,t,n),fill:(t,n,r,i)=>T(e,t,n,r,i),scroll:(t,n)=>te(e,t,n),performGesture:t=>x(e,t),gestureViewport:()=>v(e),screenshot:(t,n)=>J(e,t,n),snapshot:async t=>{let i=t??{},a=await o(`snapshot_capture`,async()=>await O(e,{appBundleId:i.appBundleId,signal:i.signal??n?.signal,interactiveOnly:i.interactiveOnly,depth:i.depth,scope:i.scope,raw:i.raw,includeHiddenContentHints:i.includeHiddenContentHints,helperSessionScope:i.appBundleId?`daemon-session`:`command`}),{backend:`android`});return{nodes:a.nodes??[],truncated:a.truncated??!1,backend:`android`,...r(a)}},back:t=>S(e),home:()=>C(e),setOrientation:t=>_(e,t),appSwitcher:()=>E(e),tvRemote:(t,n)=>D(e,t,n),readClipboard:()=>m(e),writeClipboard:t=>h(e,t),setSetting:(t,n,r,i)=>F(e,t,n,r,i)};return t?M(i,n=>c(t,{serial:e.id},n)):i}export{$ as n,ne as t};
|
package/dist/src/app-helpers.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{n as e}from"./rolldown-runtime.js";import{p as t}from"./device.js";import{n}from"./sdk-android-adb.js";import{d as r,v as i,y as a}from"./app-lifecycle.js";var o=e({getAndroidAppStateWithAdb:()=>u,listAndroidAppsWithAdb:()=>l});const s=`android.intent.category.LAUNCHER`,c=`android.intent.category.LEANBACK_LAUNCHER`;async function l(e,n={}){let i=await d(e,n.target??`auto`);return(t(n.filter)===`user-installed`?(await h(e)).filter(e=>i.has(e)):Array.from(i)).map(e=>({package:e,name:r(e)})).sort((e,t)=>e.package.localeCompare(t.package))}async function u(e){return await g(e,[[`shell`,`dumpsys`,`window`,`windows`],[`shell`,`dumpsys`,`window`]])||await g(e,[[`shell`,`dumpsys`,`activity`,`activities`],[`shell`,`dumpsys`,`activity`]])||{}}async function d(e,t){let n=(await Promise.all(f(t).map(async t=>{let n=await e(p(t),{allowFailure:!0});return n.exitCode===0?m(n.stdout):[]}))).flat();return new Set(n)}function f(e){switch(e){case`mobile`:return[s];case`tv`:return[c];default:return[s,c]}}function p(e){return[`shell`,`cmd`,`package`,`query-activities`,`--brief`,`-a`,`android.intent.action.MAIN`,`-c`,e]}function m(e){return e.trim().length===0?[]:i(e)}async function h(e){let t=await e([`shell`,`pm`,`list`,`packages`,`-3`],{allowFailure:!0});if(t.exitCode!==0)throw n(`Failed to list Android user-installed apps`,t);return a(t.stdout)}async function g(e,t){let{parseAndroidForegroundApp:n}=await import(`./platform-runtime.js`).then(e=>e.r);for(let r of t){let t=await n((await e(r,{allowFailure:!0})).stdout??``);if(t)return t}return null}export{u as n,l as r,o as t};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`)){let e=n.trim();if(!e)continue;let r=e.split(/\s+/)[0]??``;if(!r.includes(`/`))continue;let i=r.split(`/`)[0]??``;i.includes(`.`)&&i&&t.add(i)}return Array.from(t)}function
|
|
3
|
-
`).map(e=>{let t=e.trim();return t.startsWith(`package:`)?t.slice(8):t}).filter(Boolean)}function
|
|
4
|
-
`);for(let e of re)for(let r of n){let n=r.indexOf(e);if(n===-1)continue;let i=r.trim(),a=t(r.slice(n+e.length),i);if(a)return a}return null}function ce(e,t){let n=e.split(`}`)[0]?.trim()??e.trim(),r=
|
|
5
|
-
`).map(e=>e.replace(`package:`,``).trim()).filter(Boolean).filter(e=>e.toLowerCase().includes(r.toLowerCase())),c=s[0];if(c!==void 0&&s.length===1)return
|
|
6
|
-
`).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
|
|
7
|
-
`).map(e=>e.replace(`package:`,``).trim()).filter(Boolean))}async function Ve(e,t){let n=await Z(e),r=Array.from(n).filter(e=>!t.has(e));if(r.length===1)return r[0]}async function Q(e,t){await D.invalidateWhile(O(e),async()=>{e.booted||await p(e.id),await Be(e,t)})}async function $(e,t,n){let r=n?void 0:await Z(e);return await Q(e,t),n??(r?await Ve(e,r):void 0)}async function He(e,t){e.booted||await p(e.id);let n=await f({kind:`path`,path:t});try{let t=await $(e,n.installablePath,n.packageName),r=t?M(t):void 0;return{archivePath:n.archivePath,installablePath:n.installablePath,packageName:t,appName:r,launchTarget:t}}finally{await n.cleanup()}}async function Ue(e,t,n){return await D.invalidateWhile(O(e),async()=>{e.booted||await p(e.id);let{package:r}=await Fe(e,t),i=await f({kind:`path`,path:n},{resolveIdentity:!1});try{await Q(e,i.installablePath)}finally{await i.cleanup()}return{package:r}})}export{M as a,R as c,k as d,x as f,_ as g,g as h,P as i,G as l,v as m,K as n,U as o,pe as p,N as r,A as s,me as t,W as u};
|
|
1
|
+
import{n as e}from"./rolldown-runtime.js";import{_ as t,v as n}from"./sdk-contracts.js";import{J as r}from"./sdk-batch-runner.js";import{_ as i,n as a,o,r as s,s as c}from"./sdk-android-adb.js";import{n as l}from"./shell-quote.js";import{t as u}from"./timeouts.js";import"./sdk.js";import{i as ee,n as d,o as te,t as ne}from"./boot-diagnostics.js";const re=[`mCurrentFocus=Window{`,`mFocusedApp=AppWindowToken{`,`mResumedActivity:`,`ResumedActivity:`],f=/\bApplication Not Responding:\s*([A-Za-z0-9_.]+)/i,ie=/([^{}]*\bis(?:n't| not)\s+responding[^{}]*)/i,ae=/\b([A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z0-9_]+)+)\b/;function p(e){let t=new Set;for(let n of e.split(`
|
|
2
|
+
`)){let e=n.trim();if(!e)continue;let r=e.split(/\s+/)[0]??``;if(!r.includes(`/`))continue;let i=r.split(`/`)[0]??``;i.includes(`.`)&&i&&t.add(i)}return Array.from(t)}function m(e){return e.split(`
|
|
3
|
+
`).map(e=>{let t=e.trim();return t.startsWith(`package:`)?t.slice(8):t}).filter(Boolean)}function oe(e){return se(e,(e,t)=>ce(e,t))}function se(e,t){let n=e.split(`
|
|
4
|
+
`);for(let e of re)for(let r of n){let n=r.indexOf(e);if(n===-1)continue;let i=r.trim(),a=t(r.slice(n+e.length),i);if(a)return a}return null}function ce(e,t){let n=e.split(`}`)[0]?.trim()??e.trim(),r=f.exec(n);if(r){let e=r[1];return{package:e,focusedWindow:`Application Not Responding: ${e}`,raw:t}}let i=ie.exec(n);if(!i)return null;let a=i[1];if(a===void 0)return null;let o=a.trim().replace(/\s+/g,` `),s=ae.exec(o)?.[1];return{...s?{package:s}:{},focusedWindow:o,raw:t}}function h(e={}){let t=e.ttlMs??3e4,n=e.nowMs??Date.now,r=new Map,i=e=>{let t=le(e);for(let e of r.keys())e.startsWith(t)&&r.delete(e)};return{get(e,t){let i=g(e,t),a=r.get(i);if(a){if(a.expiresAtMs<=n()){r.delete(i);return}return a.value}},set(e,i,a){return r.set(g(e,i),{value:a,expiresAtMs:n()+t}),a},clear(e){i(e)},async invalidateWhile(e,t){i(e);try{return await t()}finally{i(e)}}}}function g(e,t){return[e.platform,e.deviceId,e.variant??``,t.trim().toLowerCase()].join(`\0`)}function le(e){return[e.platform,e.deviceId,``].join(`\0`)}var _=e({isClipboardShellUnsupported:()=>y,runAndroidAdb:()=>v});async function v(e,t,n){return await o(e)(t,n)}function y(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`no shell command implementation`)||n.includes(`unknown command`)}var ue=e({classifyAndroidAppTarget:()=>b,formatAndroidInstalledPackageRequiredMessage:()=>pe});const de=/\.(?:apk|aab)$/i,fe=/^[A-Za-z_][\w]*(\.[A-Za-z_][\w]*)+$/;function b(e){let t=e.trim();return t.length===0?`other`:de.test(t)?t.includes(`/`)||t.includes(`\\`)||t.startsWith(`.`)||t.startsWith(`~`)||!x(t)?`binary`:`package`:x(t)?`package`:`other`}function x(e){return fe.test(e)}function pe(e){return`Android runtime hints require an installed package name, not "${e}". Install or reinstall the app first, then relaunch by package.`}var me=e({androidAppsDiscoveryHint:()=>S,inferAndroidAppName:()=>E,resolveAndroidApp:()=>T,withAndroidAppResolutionCacheInvalidated:()=>ge});const he={settings:{type:`intent`,value:`android.settings.SETTINGS`}},S=`Run agent-device apps --platform android to discover the installed package name, then retry open with that exact package.`,C=h();function w(e){return{platform:`android`,deviceId:e.id,variant:e.target??``}}async function ge(e,t){return await C.invalidateWhile(w(e),t)}async function T(e,n){let r=n.trim();if(b(r)===`package`)return{type:`package`,value:r};let i=he[r.toLowerCase()];if(i)return i;let a=w(e),o=C.get(a,r);if(o)return o;let s=(await v(e,[`shell`,`pm`,`list`,`packages`])).stdout.split(`
|
|
5
|
+
`).map(e=>e.replace(`package:`,``).trim()).filter(Boolean).filter(e=>e.toLowerCase().includes(r.toLowerCase())),c=s[0];if(c!==void 0&&s.length===1)return C.set(a,r,{type:`package`,value:c});throw s.length>1?new t(`INVALID_ARGS`,`Multiple packages matched "${n}"`,{matches:s,hint:`Run agent-device apps --platform android to see the exact installed package names before retrying open.`}):new t(`APP_NOT_INSTALLED`,`No package found matching "${n}"`,{hint:S})}function E(e){let t=new Set([`com`,`android`,`google`,`app`,`apps`,`service`,`services`,`mobile`,`client`]),n=e.split(`.`).flatMap(e=>e.split(/[_-]+/)).map(e=>e.trim().toLowerCase()).filter(e=>e.length>0),r=n[n.length-1]??e;for(let e=n.length-1;e>=0;--e){let i=n[e];if(i&&!t.has(i)){r=i;break}}return r.split(/[^a-z0-9]+/i).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `)}var _e=e({waitForAndroidBoot:()=>O});const D=1e4;async function ve(e,t=D,n){return await i(`adb`,[`-s`,e,`shell`,`getprop`,`sys.boot_completed`],{allowFailure:!0,signal:n,timeoutMs:t})}async function O(e,n=6e4,r){let i=ee.fromTimeoutMs(n),a=Math.min(1e3,Math.max(50,Math.floor(n/20))),o=Math.max(1,Math.ceil(n/a)),s,c=!1;try{await te(async({deadline:a})=>{if(a?.isExpired())throw c=!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),l=await ve(e,Math.min(o,D),r);if(s=l,l.stdout.trim()!==`1`)throw new t(`COMMAND_FAILED`,`Android device is still booting`,{serial:e,stdout:l.stdout,stderr:l.stderr,exitCode:l.exitCode})},{maxAttempts:o,baseDelayMs:a,maxDelayMs:a,jitter:0,shouldRetry:e=>{let t=d({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=>d({error:e,stdout:s?.stdout,stderr:s?.stderr,context:{platform:`android`,phase:`boot`}})})}catch(t){k({error:t,serial:e,timeoutMs:n,deadline:i,lastBootResult:s,timedOut:c})}}function k(e){let t=n(e.error),r=A(e,t);throw M(t,r,e.timedOut,j(e,r))}function A(e,t){let n=d({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 j(e,t){return{serial:e.serial,timeoutMs:e.timeoutMs,elapsedMs:e.deadline.elapsedMs(),reason:t,hint:ne(t),stdout:e.lastBootResult?.stdout,stderr:e.lastBootResult?.stderr,exitCode:e.lastBootResult?.exitCode,...n(e.error).details??{}}}function M(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 N=e({closeAndroidApp:()=>Z,getAndroidAppState:()=>R,getAndroidBlockingDialogFocus:()=>z,isAmStartError:()=>J,listAndroidApps:()=>Se,openAndroidApp:()=>H,openAndroidDevice:()=>X,parseAndroidLaunchComponent:()=>Y});const P=`android.intent.category.LAUNCHER`,F=`android.intent.category.LEANBACK_LAUNCHER`,I=`android.intent.category.DEFAULT`,ye=new Set([`localhost`,`127.0.0.1`,`::1`,`[::1]`]),be=[[`shell`,`dumpsys`,`window`,`windows`],[`shell`,`dumpsys`,`window`],[`shell`,`dumpsys`,`activity`,`activities`],[`shell`,`dumpsys`,`activity`]],xe=/(?:(mCurrentFocus=Window\{)|(mFocusedApp=AppWindowToken\{)|(mResumedActivity:)|(ResumedActivity:))(.*)$/gm;async function Se(e,t){let n=await Ce(e);return(t===`user-installed`?(await Te(e)).filter(e=>n.has(e)):Array.from(n)).sort((e,t)=>e.localeCompare(t)).map(e=>({package:e,name:E(e)}))}async function Ce(e){let t=new Set;for(let n of L(e,{includeFallbackWhenUnknown:!0})){let r=await v(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 p(r.stdout))t.add(e)}return t}function we(e){return L(e)[0]??P}function L(e,t={}){return e.target===`tv`?[F]:e.target===`mobile`?[P]:t.includeFallbackWhenUnknown?[P,F]:[P]}async function Te(e){return m((await v(e,[`shell`,`pm`,`list`,`packages`,`-3`])).stdout)}async function R(e){for(let t of be){let n=ze((await v(e,[...t],{allowFailure:!0})).stdout??``);if(n)return n}return{}}async function z(e){return await Ee(e,[[`shell`,`dumpsys`,`window`,`windows`],[`shell`,`dumpsys`,`window`]])}async function Ee(e,t){for(let n of t){let t=oe((await v(e,n,{allowFailure:!0})).stdout??``);if(t)return t}return null}function De(e){let t;try{t=new URL(e)}catch{return null}let n=t.hostname.toLowerCase();if(!ye.has(n)||!t.port)return null;let r=Number(t.port);return Number.isInteger(r)?`tcp:${r}`:null}async function B(e,n){let r=De(n);if(!r)return;let i=s(c(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 V(e){return(e.launchArgs??[]).map(l)}async function H(e,t,n){e.booted||await O(e.id);let i=Pe(n),a=i.activity,o=t.trim();if(r(o)){await Oe(e,o,i);return}if(i.url!==void 0){await ke(e,t,i);return}let s=await T(e,t),c=we(e);if(s.type===`intent`){await Ae(e,s.value,i);return}if(a){await je(e,s.value,a,c,i);return}await Me(e,s.value,c,i)}async function Oe(e,n,r){if(r.activity)throw new t(`INVALID_ARGS`,`Activity override is not supported when opening a deep link URL`);await B(e,n),await v(e,[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.VIEW`,`-d`,l(n),...Fe(r.appBundleId),...V(r)])}async function ke(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 B(e,a);let o=await Ne(e,n,`app-bound open`);await v(e,[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.VIEW`,`-d`,l(a),`-p`,o,...V(i)])}async function Ae(e,n,r){if(r.activity)throw new t(`INVALID_ARGS`,`Activity override requires a package name, not an intent`);await v(e,[`shell`,`am`,`start`,`-W`,`-a`,n,...V(r)])}async function je(e,t,n,r,i){let a=n.includes(`/`)?n:`${t}/${n.startsWith(`.`)?n:`.${n}`}`;try{await v(e,U(a,r,i))}catch(n){throw await Ie(e,t,n),n}}async function Me(e,t,n,r){let i=await v(e,[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,I,`-c`,n,`-p`,t,...V(r)],{allowFailure:!0});if(i.exitCode===0&&!J(i.stdout,i.stderr))return;let o=await q(e,t);if(!o)throw await G(e,t)?a(`Failed to launch ${t}`,i):W(t);await v(e,U(o,n,r))}function U(e,t,n){return[`shell`,`am`,`start`,`-W`,`-a`,`android.intent.action.MAIN`,`-c`,I,`-c`,t,`-n`,e,...V(n)]}async function Ne(e,n,r){let i=await T(e,n);if(i.type===`intent`)throw new t(`INVALID_ARGS`,`Android ${r} requires a package name, not an intent`);return i.value}function Pe(e){return typeof e==`string`?{activity:e}:e??{}}function Fe(e){let t=e?.trim();return t?[`-p`,t]:[]}function W(e){return new t(`APP_NOT_INSTALLED`,`No package found matching "${e}"`,{package:e,hint:S})}async function G(e,t){let n=await v(e,[`shell`,`pm`,`path`,t],{allowFailure:!0}),r=`${n.stdout}\n${n.stderr}`;return n.exitCode===0&&/\bpackage:/i.test(r)?!0:(K(r),!1)}async function Ie(e,n,r){if(K(r instanceof t?`${String(r.details?.stdout??``)}\n${String(r.details?.stderr??``)}`:``)||!await G(e,n))throw W(n)}function K(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 q(e,t){let n=Array.from(new Set(L(e,{includeFallbackWhenUnknown:!0})));for(let r of n){let n=await v(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){let n=`${e}\n${t}`;return/Error:.*(?:Activity not started|unable to resolve Intent)/i.test(n)}function Y(e){let t=e.split(`
|
|
6
|
+
`).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 O(e.id)}async function Z(e,n){if(n.trim().toLowerCase()===`settings`){await v(e,[`shell`,`am`,`force-stop`,`com.android.settings`]),await Q(e,`com.android.settings`);return}let r=await T(e,n);if(r.type===`intent`)throw new t(`INVALID_ARGS`,`Close requires a package name, not an intent`);await v(e,[`shell`,`am`,`force-stop`,r.value]),await Q(e,r.value)}async function Q(e,t){await Le(e,t),await Be(e,t)}async function Le(e,t){let n=Date.now()+2e3;for(;Date.now()<n;){if((await Re(e))?.package!==t)return;await u(50)}}async function Re(e){let t=await R(e);return t.package?t:null}function ze(e){for(let t of e.matchAll(xe)){let e=t[5]?.match(/\b([A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z0-9_]+)+)\/([A-Za-z0-9_.$]+)/);if(e?.[1]&&e[2])return{package:e[1],activity:e[2]}}return null}async function Be(e,t){let n=Date.now()+2e3;for(;Date.now()<n;){if(!await $(e,t)&&(await u(150),!await $(e,t)))return;await u(50)}}async function $(e,t){return((await v(e,[`shell`,`pidof`,t],{allowFailure:!0})).stdout??``).trim().length>0}export{h as _,J as a,Y as c,E as d,T as f,v as g,y as h,z as i,_e as l,_ as m,Z as n,H as o,ue as p,R as r,X as s,N as t,me as u,p as v,m as y};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`).map(e=>e.trim()).filter(e=>/^([a-zA-Z0-9_]+\.)+[a-zA-Z0-9_]+$/.test(e))}function
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import"./sdk-android-adb.js";import{n as t}from"./hdc.js";function n(e){return e.split(`
|
|
2
|
+
`).map(e=>e.trim()).filter(e=>/^([a-zA-Z0-9_]+\.)+[a-zA-Z0-9_]+$/.test(e))}function r(e){let t=a(e);if(!t)return;let n=t.hapModuleInfos?.find(e=>e.mainElementName);if(n?.mainElementName)return{ability:n.mainElementName,module:n.moduleName}}function i(e){let t=a(e),n=t?.applicationInfo?.isSystemApp??t?.appInfo?.isSystemApp;return typeof n==`boolean`?n:void 0}function a(e){let t=e.indexOf(`{`);if(t!==-1)try{return JSON.parse(e.slice(t))}catch{return}}async function o(r,i,a={}){if(i===`all`)return s(n((await t(r,[`shell`,`bm`,`dump`,`-a`],{timeoutMs:15e3,signal:a.signal})).stdout));let o=new AbortController,u=setTimeout(()=>o.abort(),6e4),d=l(a.signal,o.signal);try{return s(await c(r,n((await t(r,[`shell`,`bm`,`dump`,`-a`],{timeoutMs:15e3,signal:d})).stdout),d))}catch(t){throw o.signal.aborted?new e(`COMMAND_FAILED`,`Timed out while classifying HarmonyOS application inventory`,{hint:`Use apps --all to list bundles without per-bundle classification, then retry after the device is responsive.`}):t}finally{clearTimeout(u)}}function s(e){return e.map(e=>({package:e,name:e.split(`.`).at(-1)??e}))}async function c(n,r,a){let o=Array(r.length),s=new AbortController,c=l(a,s.signal),u=0,d,f=Math.min(4,r.length),p=Array.from({length:f},async()=>{try{for(;;){c?.throwIfAborted();let a=u++;if(a>=r.length)return;let s=r[a];if(!s)return;let l=i((await t(n,[`shell`,`bm`,`dump`,`-n`,s],{timeoutMs:15e3,signal:c})).stdout);if(l===void 0)throw new e(`COMMAND_FAILED`,`Could not determine whether ${s} is a system application`,{hint:`Use apps --all to list all bundles when Bundle Manager does not expose applicationInfo.isSystemApp.`});o[a]=l}}catch(e){throw!c?.aborted&&d===void 0&&(d=e),s.abort(),e}}),m=await Promise.allSettled(p);if(d!==void 0)throw d;let h=m.find(e=>e.status===`rejected`);if(h)throw h.reason;return r.filter((e,t)=>!o[t])}function l(...e){let t=e.filter(e=>!!e);if(t.length!==0)return t.length===1?t[0]:AbortSignal.any(t)}async function u(n,i,a){let o=a?.activity?{ability:a.activity}:r((await t(n,[`shell`,`bm`,`dump`,`-n`,i],{signal:a?.signal,timeoutMs:15e3})).stdout);if(!o)throw new e(`COMMAND_FAILED`,`Could not determine a launchable ability for ${i}`,{hint:`Pass --activity with the HarmonyOS ability name, or check that the bundle is installed.`});let s=[`shell`,`aa`,`start`,`-a`,o.ability,`-b`,i];o.module&&s.push(`-m`,o.module);let c=await t(n,s,{signal:a?.signal});if(!c.stdout.includes(`start ability successfully`))throw new e(`COMMAND_FAILED`,`Failed to start ${i}`,{details:{output:c.stdout.trim()}})}async function d(e,n){await t(e,[`shell`,`aa`,`force-stop`,n])}export{d as closeHarmonyApp,o as listHarmonyApps,u as openHarmonyApp};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{ht as e}from"./sdk-batch-runner.js";import{NotFoundError as t}from"@limrun/api";import{createInstanceClient as n}from"@limrun/api/instance-client";import{createInstanceClient as r}from"@limrun/api/ios-client";async function i(e){try{return e.descriptor.platform===`ios`?await a(e):await o(e)}catch(e){if(e instanceof t)return{status:`missing`};throw e}}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:n}=t,i=await r({apiUrl:t.apiUrl,token:n.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(t){let r=await s(async()=>await t.limrun.androidInstances.get(t.descriptor.instanceId,{timeout:5e3,maxRetries:0,signal:t.signal}),t.descriptor);if(r.status!==`active`)return r;let{instance:i}=r;if(!i.status.adbWebSocketUrl)return{status:`missing`};let a=await n({apiUrl:r.apiUrl,adbUrl:i.status.adbWebSocketUrl,token:i.status.token,logLevel:`warn`}),o=new e,c=!1;o.defer(async()=>{c||a.disconnect()});try{let e=await a.startAdbTunnel();o.defer(async()=>{c||e.close()});let n=`${e.address.address}:${e.address.port}`,r=async(e,r)=>await t.dependencies.host.runAdb([`-s`,n,...e],r),i={platform:`android`,leaseId:t.descriptor.leaseId,instanceId:t.descriptor.instanceId,readLogs:async(e,n)=>await t.dependencies.android.readLogs(r,n),[Symbol.asyncDispose]:async()=>{await t.dependencies.host.runAdb([`disconnect`,n],{allowFailure:!0,timeoutMs:1e4}).catch(()=>void 0);let r=(await Promise.allSettled([Promise.resolve().then(()=>e.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{_ as e}from"./sdk-contracts.js";import{
|
|
2
|
-
`)?r:`${r}\n`),a=`active`}catch{if(o)return;a=`recovering`}await e.host.clock.sleep(1e3)}})(),
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{At as t,B as n,H as r,Ot as i,ct as a,dt as o,ht as s,lt as c,ot as l,rt as u,ut as d}from"./sdk-batch-runner.js";import{c as ee}from"./sdk-device.js";import{a as f,i as te,s as p}from"./src.js";import{c as ne,g as m,h,m as g,n as _,s as v,v as y,x as b}from"./src3.js";const x=Object.freeze({resourceKind:u,version:1,encode:e=>({...e}),decode:e=>e.transport!==`limrun-log-poller`||e.platform!==`ios`&&e.platform!==`android`||!S(e.leaseId)||!S(e.instanceId)||!S(e.appBundleId)||!S(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 re(e){if(e.device.platform===`apple`&&!e.device.appleOs)throw TypeError(`Limrun Apple app-log persistence requires an explicit appleOs identity`);return y({resourceKind:u,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:b(x,e.descriptor)})}function S(e){return typeof e==`string`&&e.trim().length>0}async function C(e){let t=new s,n=!1;t.defer(async()=>{n||await e.reader[Symbol.asyncDispose]()});try{let r=await e.host.outputs.readTail(e.outputPath,256*1024),i=await e.host.outputs.openAppend(e.outputPath);t.defer(async()=>{n||await i[Symbol.asyncDispose]()});let a=ie(e,i,T(r));return n=!0,a}finally{await t[Symbol.asyncDispose]()}}function ie(e,t,n){let r=D(e.reader),i=e.host.clock.now(),a=`active`,o=!1,s=n,c=(async()=>{for(;!o;){try{let n=await ae(e);if(n.status===`timeout`){a=`failed`;return}if(o)return;let r=oe(s,n.text);s=n.text,r&&await t.write(r.endsWith(`
|
|
2
|
+
`)?r:`${r}\n`),a=`active`}catch{if(o)return;a=`recovering`}await e.host.clock.sleep(1e3)}})(),l;return g({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 ae(e){let t=new AbortController,n=te(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 oe(e,t){if(!e||!t)return t;let n=se(t),r=Math.min(e.length,t.length),i=e.slice(e.length-r);return t.slice(w(i,t,n))}function se(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 w(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 T(e){return e.split(`
|
|
3
3
|
`).filter(e=>!e.startsWith(`[agent-device][mark]`)).join(`
|
|
4
|
-
`)}async function
|
|
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 D(e){return e.platform===`ios`?`ios-simulator`:`android`}function O(e){return n({owner:`Limrun`,openTargetIdentity:`bundle-id`,closeBeforeRelaunch:!0,configureProviderPortReverse:async t=>await e.configurePortReverse(t),binding:r({device:e.device,signal:e.signal,resolveInteractor:t=>e.getInteractor(e.device,t)})})}function k(e){let t=p(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 A=Object.freeze({available:!0}),j=Object.freeze({available:!1,reason:`owner-capability-missing`,hint:`The Limrun provider session is no longer active for this device.`}),M=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Push notifications are unavailable for Limrun provider-owned devices.`});function N(e,t){let n=F(e,t);return Object.freeze({deployApp:n,materializeAppSource:n,deployMaterializedApp:n,sendPushNotification:I(e,t)?M:j})}function P(e,t,n,r){let i=e.deployApp,a=e.deployMaterializedApp;return!N(e,t).deployApp.available||!i||!a?Object.freeze({}):Object.freeze({deployApp:async e=>R(await i(t,e,n,r)),materializeAppSource:async r=>await L(e.host,t,r,n),deployMaterializedApp:async e=>R(await a(t,e,n,r))})}function F(e,t){return k(t)&&I(e,t)&&e.deployApp&&e.deployMaterializedApp?A:j}function I(e,t){return e.isSessionActive?.(t)??e.ownsDevice(t)}async function L(e,t,n,r){return await(t.platform===`apple`?e.appleDeployment:e.androidDeployment).prepareArtifact(n,{signal:r})}function R(t){if(!t)throw new e(`UNSUPPORTED_OPERATION`,`The Limrun provider session is no longer active.`);return t}function z(e){return{...e,isSessionActive:e.hasLiveSession}}const B=Object.freeze({available:!0}),V=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Custom snapshot actions are available only for Limrun iOS simulator sessions.`}),H=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun does not expose an exact-owner screen-recording runtime.`}),U=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Headless boot is unavailable for provider-owned devices.`}),W=Object.freeze({available:!1,reason:`owner-capability-missing`,hint:`Limrun requires a matching live provider session for this device.`}),G=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Apple runner preparation is unavailable for Limrun-owned devices.`}),K=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun open requires a Limrun-owned iOS simulator or Android emulator.`}),ce=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun close requires a Limrun-owned iOS simulator or Android emulator.`}),q=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Runtime hints are not applied to provider-owned devices.`}),le=Object.freeze({available:!1,reason:`unsupported-provider-mode`,hint:`Limrun port reverse requires an active Android Limrun session.`});function J(e,t){let n=ue(e,t),r=de(e,t),i=fe(e,t);return d({resolveOpenTarget:n,prepareApplicationOpen:n,openApplication:n,applyRuntimeHints:q,clearRuntimeHints:q,closeApplication:r,finalizeApplicationClose:r,prepareAppleRunner:G,configureProviderPortReverse:i})}function ue(e,t){return Q(e)?t?B:W:K}function de(e,t){return Q(e)?t?B:W:ce}function fe(e,t){return t?e.platform===`android`?B:le:W}function pe(n){let r=i(`limrun`,n.runtimeInstance),a=e=>Q(e)&&n.ownsDevice(e),o=e=>a(e)&&n.hasLiveSession(e);return Object.freeze({owner:r,ownsDevice:a,inspectFacts:async e=>o(e)?Y(n,e):l(e,r,{appLog:W,appState:W,appDeployment:W,network:W,readiness:W,shutdown:W,lifecycle:J(e,!1)}),bind:async i=>{if(i.intent.kind===`exact-owner`&&!t(i.intent.owner,r))throw new e(`UNSUPPORTED_OPERATION`,`Limrun app-log owner identity does not match`);if(!Q(i.device))throw new e(`UNSUPPORTED_PLATFORM`,`Limrun app logs require an iOS simulator or Android emulator device identity`);let a=o(i.device);if(i.intent.kind!==`exact-owner`&&!a)throw new e(`UNSUPPORTED_OPERATION`,`Limrun provider session is no longer live for the selected device`,{reason:`provider-session-unavailable`});return me(n,r,i.device,i.scope.signal,!a)},shutdown:async()=>void 0})}function me(t,n,r,i,s){let c=s?ge(t,r):Y(t,r),l=f(),u=h({codec:x,reattach:async(e,n)=>{if(!Z(e,r)||!v(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 C({host:t.host,reader:a.reader,appBundleId:e.appBundleId,outputPath:e.outputPath})}},cleanup:async(e,n)=>Z(e,r)&&v(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:X(r)}),appLogDoctor:async()=>({backend:X(r),checks:{limrunSessionAvailable:await he(t,r,i)},notes:[]}),appLogStart:async a=>{ne(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=re({sessionId:a.sessionId,device:r,owner:n,fence:a.fence,descriptor:s});return c=!0,m(await C({host:t.host,reader:o,appBundleId:a.appBundleId,outputPath:a.outputPath}),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=X(r),a=_(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)}:{},...o(O({device:r,signal:i,getInteractor:t.getInteractor,configurePortReverse:t.configurePortReverse}),c.operations),...a({device:r,signal:i,resolveInteractor:e=>t.getInteractor(r,e)}),...P(z(t),r,i,l)};return Object.freeze({device:r,owner:n,facts:c,operations:Object.freeze(s?{appLogReattach:u.appLogReattach,appLogCleanup:u.appLogCleanup}:d),[Symbol.asyncDispose]:async()=>await l[Symbol.asyncDispose]()})}async function he(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 Y(e,t){let n=N(z(e),t);return Object.freeze({device:{family:t.platform,...t.appleOs===void 0?{}:{appleOs:t.appleOs},kind:t.kind,...t.target===void 0?{}:{target:t.target},...t.iosPhysicalDeviceBackend===void 0?{}:{iosPhysicalDeviceBackend:t.iosPhysicalDeviceBackend},providerMode:`provider-runtime`},operations:{appLogInspect:B,appLogDoctor:B,appLogStart:B,appLogReattach:B,appLogCleanup:B,...n,appState:t.platform===`android`?B:{available:!1,reason:`unsupported-provider-mode`,hint:`Limrun iOS appstate is session-owned; no sessionless provider foreground probe is exposed.`},networkDump:B,screenRecordingStart:H,screenRecordingReattach:H,screenRecordingCleanup:H,...c({capture:B,customActions:ee(t)&&t.kind===`simulator`?B:V,withoutActiveApp:B}),ensureReady:B,bootTarget:B,bootTargetHeadless:U,listApps:B,shutdownTarget:{available:!1,reason:`unsupported-provider-mode`,hint:`Limrun owns the target lifecycle for provider-owned devices.`},...J(t,!0)}})}function ge(e,t){let n=Y(e,t);return Object.freeze({device:n.device,operations:{...n.operations,appLogInspect:W,appLogDoctor:W,appLogStart:W,appLogReattach:B,appLogCleanup:B,appState:W,networkDump:W,screenRecordingStart:W,screenRecordingReattach:W,screenRecordingCleanup:W,...c({capture:W,customActions:W,withoutActiveApp:W}),ensureReady:W,bootTarget:W,bootTargetHeadless:W,listApps:W,deployApp:W,materializeAppSource:W,deployMaterializedApp:W,sendPushNotification:W,shutdownTarget:W,...J(t,!1)}})}function X(e){return e.platform===`apple`?`ios-simulator`:`android`}function Z(e,t){if(!Q(t))return!1;let n=p(t.id);return n!==void 0&&n.leaseId===e.leaseId&&n.platform===e.platform&&(t.platform===`apple`?e.platform===`ios`:e.platform===`android`)}function Q(e){let t=p(e.id);return!t||e.target!==`mobile`?!1:t.platform===`ios`?$(e):_e(e)}function $(e){return e.platform===`apple`&&e.appleOs===`ios`&&e.kind===`simulator`&&e.iosPhysicalDeviceBackend===void 0}function _e(e){return e.platform===`android`&&e.appleOs===void 0&&e.kind===`emulator`&&e.iosPhysicalDeviceBackend===void 0}export{pe as createLimrunPlatformRuntimeOwner};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`)){let t=z.exec(e);t?.[1]&&n.push(t[1])}return n}async function H(e,t){if(!r(e)||e.kind!==`simulator`)return;let n=U(t);if(!n)return;let i=await K(e),a=[];for(let e of i)e.bundleId.startsWith(`com.callstack.agentdevice.runner`)||e.path&&(await J(p.join(e.path,`Info.plist`))).has(n)&&a.push(e);let o=a.filter(e=>e.applicationType===`User`);if(o.length===1)return o[0]?.bundleId;if(!(o.length>1))return a.length===1?a[0]?.bundleId:void 0}function U(e){return/^([A-Za-z][A-Za-z0-9+.-]*):/.exec(e.trim())?.[1]?.toLowerCase()}async function W(e,t){return i(e)?await D(t):e.kind===`simulator`?
|
|
1
|
+
import{n as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{J as n}from"./sdk-batch-runner.js";import{c as r,l as i}from"./sdk-device.js";import{_ as a}from"./app-lifecycle.js";import{t as o}from"./appearance.js";import{i as s,r as c,s as l}from"./tool-provider.js";import{a as u,n as d}from"./physical-device-control.js";import{n as f}from"./helper.js";import p from"node:path";import{fileURLToPath as m}from"node:url";const h={settings:`com.apple.systempreferences`},g=/^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/,_={platform:`macos`,deviceId:`host`,variant:`all`},v=a();function y(e){return g.test(e)}async function b(e){let n=e.trim(),r=h[n.toLowerCase()];if(r)return r;if(y(n))return n;let i=v.get(_,n);if(i)return i;let a=(await D(`all`)).filter(e=>e.name.toLowerCase()===n.toLowerCase()),o=a[0];if(o!==void 0&&a.length===1)return v.set(_,n,o.bundleId);throw a.length>1?new t(`INVALID_ARGS`,`Multiple apps matched "${e}"`,{matches:a}):new t(`APP_NOT_INSTALLED`,`No app found matching "${e}"`)}async function x(e,r,i){let a=i?.url?.trim();if(a){if(!n(a))throw new t(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);let e=i?.appBundleId??await b(r);await O().openBundle(e,a);return}let o=r.trim();if(n(o)){await O().openTarget(o);return}let s=i?.appBundleId??await b(o);await O().openBundle(s)}async function S(e,n){let r=await b(n),i=await f(r);if(!(!i.running||i.terminated||i.forceTerminated))throw new t(`COMMAND_FAILED`,`Failed to close macOS app ${n}`,{bundleId:r,running:i.running,terminated:i.terminated,forceTerminated:i.forceTerminated})}async function C(){return await O().readClipboard()}async function w(e){await O().writeClipboard(e)}async function T(){return await O().readDarkMode()}async function E(e){let t=o(e),n=t===`toggle`?!await T():t===`dark`;await O().setDarkMode(n)}async function D(e){return await O().listApps(e)}function O(){let e=c().macosHost;if(!e)throw new t(`UNSUPPORTED_OPERATION`,`macOS host provider is not available`);return e}var k=e({buildAppNotInstalledError:()=>F,detectSoleRunningIosSimulatorApp:()=>B,findIosSimulatorInstalledApp:()=>I,invalidateIosAppResolutionCache:()=>N,listIosApps:()=>W,resolveIosApp:()=>P,resolveIosAppAlias:()=>L,resolveIosSimulatorDeepLinkBundleId:()=>H});const A={settings:`com.apple.Preferences`},j=a();function M(e){return{platform:`ios`,deviceId:e.id,variant:e.kind}}async function N(e,t){return await j.invalidateWhile(M(e),t)}async function P(e,n){if(i(e))return await b(n);let r=n.trim();if(r.includes(`.`))return r;let a=L(r);if(a!==r)return a;let o=M(e),s=j.get(o,r);if(s)return s;let c=(e.kind===`simulator`?await G(e):await d(e).listApps(e,`all`)).filter(e=>e.name.toLowerCase()===r.toLowerCase()),l=c[0];if(l!==void 0&&c.length===1)return j.set(o,r,l.bundleId);throw c.length>1?new t(`INVALID_ARGS`,`Multiple apps matched "${n}"`,{matches:c}):F(n)}function F(e){return new t(`APP_NOT_INSTALLED`,`No app found matching "${e}"`)}async function I(e,t){if(!r(e)||e.kind!==`simulator`||e.booted!==!0)return;let n=L(t.trim());if(!n)return;let i=await G(e);if(n.includes(`.`))return i.find(e=>e.bundleId===n)?.bundleId;let a=i.filter(e=>e.name.toLowerCase()===n.toLowerCase());return a.length===1?a[0]?.bundleId:void 0}function L(e){let t=e.trim();return A[t.toLowerCase()]??e}const R=3e3,z=/UIKitApplication:([^[\s]+)\[/;async function B(e){if(!(!r(e)||e.kind!==`simulator`||e.booted!==!0))try{let[t,n]=await Promise.all([V(e),G(e,{timeoutMs:R})]);if(t.length===0)return;let r=new Map(n.map(e=>[e.bundleId,e])),i=new Map;for(let e of t){let t=r.get(e);t&&i.set(t.bundleId,t)}return i.size===1?[...i.values()][0]:void 0}catch{return}}async function V(e){let t=await u(e,[`spawn`,e.id,`launchctl`,`list`],{allowFailure:!0,timeoutMs:R});if(t.exitCode!==0)return[];let n=[];for(let e of t.stdout.split(`
|
|
2
|
+
`)){let t=z.exec(e);t?.[1]&&n.push(t[1])}return n}async function H(e,t){if(!r(e)||e.kind!==`simulator`)return;let n=U(t);if(!n)return;let i=await K(e),a=[];for(let e of i)e.bundleId.startsWith(`com.callstack.agentdevice.runner`)||e.path&&(await J(p.join(e.path,`Info.plist`))).has(n)&&a.push(e);let o=a.filter(e=>e.applicationType===`User`);if(o.length===1)return o[0]?.bundleId;if(!(o.length>1))return a.length===1?a[0]?.bundleId:void 0}function U(e){return/^([A-Za-z][A-Za-z0-9+.-]*):/.exec(e.trim())?.[1]?.toLowerCase()}async function W(e,t){return i(e)?await D(t):e.kind===`simulator`?l(await G(e),t):await d(e).listApps(e,t)}async function G(e,t){return(await K(e,t)).map(e=>({bundleId:e.bundleId,name:e.name}))}async function K(e,t){let n=(await u(e,[`listapps`,e.id],{allowFailure:!0,timeoutMs:t?.timeoutMs})).stdout.trim();if(!n)return[];let r=null;if(n.startsWith(`{`))try{r=JSON.parse(n)}catch{r=null}if(!r&&n.startsWith(`{`))try{let e=await s(`plutil`,[`-convert`,`json`,`-o`,`-`,`-`],{allowFailure:!0,stdin:n,timeoutMs:t?.timeoutMs});e.exitCode===0&&e.stdout.trim().startsWith(`{`)&&(r=JSON.parse(e.stdout))}catch{r=null}return r?Object.entries(r).map(([e,t])=>{let n=q(t);return{bundleId:e,name:t.CFBundleDisplayName??t.CFBundleName??e,...n?{path:n}:{},...t.ApplicationType?{applicationType:t.ApplicationType}:{}}}):[]}function q(e){if(e.Path)return e.Path;if(e.Bundle)try{return m(e.Bundle)}catch{return}}async function J(e){let t=await s(`plutil`,[`-convert`,`json`,`-o`,`-`,e],{allowFailure:!0});if(t.exitCode!==0)return new Set;try{let e=JSON.parse(t.stdout),n=new Set;for(let t of e.CFBundleURLTypes??[])if(Array.isArray(t.CFBundleURLSchemes))for(let e of t.CFBundleURLSchemes)typeof e==`string`&&e.trim()&&n.add(e.trim().toLowerCase());return n}catch{return new Set}}export{H as a,C as c,P as i,E as l,I as n,S as o,W as r,x as s,k as t,w as u};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=[[`shell`,`dumpsys`,`window`,`windows`],[`shell`,`dumpsys`,`window`]],t=[[`shell`,`dumpsys`,`activity`,`activities`],[`shell`,`dumpsys`,`activity`]],n=[`mCurrentFocus=Window{`,`mFocusedApp=AppWindowToken{`,`mResumedActivity:`,`ResumedActivity:`];async function r(n,r,i){return await a(n,r,e,i)||await a(n,r,t,i)||{}}function i(e){let t=e.split(`
|
|
2
|
+
`);for(let e of n)for(let n of t){let t=n.indexOf(e);if(t===-1)continue;let r=o(n.slice(t+e.length));if(r)return r}return null}async function a(e,t,n,r){for(let a of n){r.throwIfAborted();let n=await e.run(t,{args:a,allowFailure:!0},r);r.throwIfAborted();let o=i(n.stdout);if(o)return o}return null}function o(e){let t=e.match(/\b([A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z0-9_]+)+)\/([A-Za-z0-9_.$]+)/);return t?.[1]&&t[2]?{package:t[1],activity:t[2]}:null}export{i as parseAndroidForegroundApp,r as readAndroidAppState};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";function t(t){let n=t.trim().toLowerCase();if(n===`light`)return`light`;if(n===`dark`)return`dark`;if(n===`toggle`)return`toggle`;throw new e(`INVALID_ARGS`,`Invalid appearance state: ${t}. Use light|dark|toggle.`)}export{t};
|
package/dist/src/apps.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`).map(e=>e.trim()).filter(e=>e.length>0&&e!==`Current Status Bar Overrides:`&&!/^=+$/.test(e));for(let e of r){let r=/^DataNetworkType:\s+(\d+)$/.exec(e);if(r){let e=Number(r[1]),i=ke[e];if(!i)throw new t(`COMMAND_FAILED`,`Unsupported simulator data network type: ${e}`);n.dataNetwork=i;continue}let i=/^WiFi Mode:\s+(\d+),\s+WiFi Bars:\s+(\d+)$/.exec(e);if(i){let e=Ae[Number(i[1])];e&&(n.wifiMode=e),n.wifiBars=i[2];continue}let a=/^Cell Mode:\s+(\d+),\s+Cell Bars:\s+(\d+)$/.exec(e);if(a){let e=Number(a[1]),r=je[e];if(!r)throw new t(`COMMAND_FAILED`,`Unsupported simulator cellular mode: ${e}`);n.cellularMode=r,n.cellularBars=a[2];continue}let o=/^Operator Name:\s*(.*)$/.exec(e);if(o){n.operatorName=o[1]??``;continue}}return Object.keys(n).length===0?null:n}function Re(e){let t=[];return e.dataNetwork&&t.push(`--dataNetwork`,e.dataNetwork),e.wifiMode&&t.push(`--wifiMode`,e.wifiMode),e.wifiBars!==void 0&&(e.dataNetwork===`wifi`||e.wifiMode)&&t.push(`--wifiBars`,e.wifiBars),e.cellularMode&&t.push(`--cellularMode`,e.cellularMode),e.cellularBars!==void 0&&(e.cellularMode||ze(e.dataNetwork)||e.operatorName!==void 0)&&t.push(`--cellularBars`,e.cellularBars),e.operatorName!==void 0&&t.push(`--operatorName`,e.operatorName),t}function ze(e){return!!(e&&e!==`hide`&&e!==`wifi`)}function B(e,t,n){h({level:`warn`,phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...b(n)}})}function V(e,t,n){return w(e,t,n)}const Be={ensureBooted:k,prepareStatusBarForScreenshot:Me,captureWithRetry:Ue,normalizeDensity:Ye,captureWithRunner:W,shouldFallbackToRunner:q},H=new Map,U=new Map;async function Ve(e,t,n={}){if(u(e)){await W(e,t,n.appBundleId,n.fullscreen,n.runnerOptions);return}if(e.kind===`simulator`){await He(e,t,n);return}await x(e).captureScreenshot(e,t,{appBundleId:n.appBundleId,fullscreen:n.fullscreen,runnerOptions:n.runnerOptions,runRunnerCommand:D})}async function He(e,n,r={}){if(e.kind!==`simulator`)throw new t(`UNSUPPORTED_OPERATION`,`Simulator screenshot fallback flow supports only iOS simulators`);let i={...Be,...r.deps??{}};r.skipIosSimulatorBootCheck||await i.ensureBooted(e);let a=async()=>{};if(r.normalizeStatusBar===!0)try{a=await i.prepareStatusBarForScreenshot(e)}catch(t){K(e,`prepare_failed`,t)}try{try{await i.captureWithRetry(e,n),await i.normalizeDensity(e,n,r.pixelDensity);return}catch(t){let a=t;if(r.skipIosSimulatorBootCheck&&Je(t)){await i.ensureBooted(e);try{await i.captureWithRetry(e,n),await i.normalizeDensity(e,n,r.pixelDensity);return}catch(e){a=e}}if(!i.shouldFallbackToRunner(a))throw a;Ke(e,`simctl_screenshot`,a)}await i.captureWithRunner(e,n,r.appBundleId,r.fullscreen,r.runnerOptions),await i.normalizeDensity(e,n,r.pixelDensity)}finally{await a().catch(t=>K(e,`restore_failed`,t))}}async function Ue(e,t){let n=g.fromTimeoutMs(fe);await _(async({deadline:n})=>{await V(e,[`io`,e.id,`screenshot`,t],{timeoutMs:Math.max(1e3,n?.remainingMs()??2e4)})},{maxAttempts:5,baseDelayMs:le,maxDelayMs:ce,jitter:.2,shouldRetry:e=>q(e)},{deadline:n,phase:`ios_simulator_screenshot`})}async function W(e,n,r,i,a){if(e.kind===`device`&&!u(e)){await x(e).captureScreenshot(e,n,{appBundleId:r,fullscreen:i,runnerOptions:a,preferRunner:!0,runRunnerCommand:D});return}let o=(await D(e,{command:`screenshot`,appBundleId:r,fullscreen:i,inlineScreenshot:!1},a)).message;if(!o)throw new t(`COMMAND_FAILED`,`Failed to capture iOS screenshot: runner returned no file path`);if(u(e)){await N.copyFile(o,n);return}if(e.kind===`simulator`){await We(e,o,n);return}throw new t(`COMMAND_FAILED`,`Unsupported Apple screenshot target`)}async function We(e,n,r){let i=g.fromTimeoutMs(y),a=`Unable to locate runner container for simulator screenshot`,o=U.get(e.id);if(o){let t=await G(o,n,r);if(t.copied)return;a=t.error,U.delete(e.id)}for(let t of se){let o=await V(e,[`get_app_container`,e.id,t,`data`],{allowFailure:!0,timeoutMs:Ge(i,y,`runner screenshot container lookup`)});if(o.exitCode!==0){let e=o.stderr.trim();e&&(a=e);continue}let s=o.stdout.trim();if(!s){a=`simctl get_app_container returned empty output`;continue}let c=await G(s,n,r);if(c.copied){U.set(e.id,s);return}a=c.error}throw new t(`COMMAND_FAILED`,`Failed to capture iOS screenshot: ${a}`)}async function G(e,t,n){let r=`Runner screenshot was not found in the simulator container`;for(let i of qe(e,t))try{return await N.copyFile(i,n),{copied:!0}}catch(e){r=e instanceof Error?e.message:String(e)}return{copied:!1,error:r}}function Ge(e,n,r){let i=e.remainingMs();if(i>0)return i;throw new t(`COMMAND_FAILED`,`iOS ${r} timed out after ${n}ms`,{timeoutMs:n,step:r})}function Ke(e,t,n){let r=b(n);h({level:`warn`,phase:`ios_screenshot_fallback`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:`runner`,...r}})}function K(e,t,n){h({level:`warn`,phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...b(n)}})}function qe(e,t){let n=M.resolve(e),r=t.trim();if(!r)return[];let i=[],a=new Set,o=e=>{let t=M.normalize(e);a.has(t)||(a.add(t),i.push(t))},s=r.replace(/^\/+/,``),c=s.replace(/\\/g,`/`);if(s&&o(M.join(n,s)),M.isAbsolute(r)&&o(M.normalize(r)),c.startsWith(`tmp/`))o(M.join(n,c));else{let e=c.lastIndexOf(`/tmp/`);if(e>=0){let t=c.slice(e+1);o(M.join(n,t))}}let l=M.basename(r);return l&&o(M.join(n,`tmp`,l)),i}function q(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=ue(e);return n.includes(`timeout waiting for screen surfaces`)||n.includes(`nsposixerrordomain`)&&n.includes(`code=60`)&&n.includes(`screenshot`)||n.includes(`timed out`)&&n.includes(`screenshot`)}function Je(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=ue(e);return n.includes(`not booted`)||n.includes(`current state: shutdown`)||n.includes(`current state is shutdown`)||n.includes(`current state=shutdown`)||n.includes(`state: shutdown`)||n.includes(`state=shutdown`)}async function Ye(e,t,n){let r=await Xe(e),i=he(await ge(t),r,n);i&&await f(t,i.width,i.height)}async function Xe(e){let n=H.get(e.id);if(n!==void 0)return n;let r=await V(e,[`getenv`,e.id,`SIMULATOR_MAINSCREEN_SCALE`],{timeoutMs:ae}),i=Number(r.stdout.trim());if(!Number.isFinite(i)||i<=0)throw new t(`COMMAND_FAILED`,`Failed to read iOS simulator screenshot scale from SIMULATOR_MAINSCREEN_SCALE`);return H.set(e.id,i),i}function J(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=e.details??{};if(n.exitCode!==4)return!1;let r=String(n.stderr??``).toLowerCase();return r.includes(`fbsopenapplicationserviceerrordomain`)&&r.includes(`the request to open`)}async function Ze(e,t){let n=await T(re(e,[`get_app_container`,e.id,t]),{allowFailure:!0});if(n.exitCode!==0)return{installed:!1};let r=n.stdout.trim();if(!r)return{installed:!1};let i=await E(`plutil`,[`-extract`,`CFBundleExecutable`,`raw`,`-o`,`-`,`${r}/Info.plist`],{allowFailure:!0});if(i.exitCode!==0||!i.stdout.trim())return{installed:!0};let a=await E(`otool`,[`-l`,`${r}/${i.stdout.trim()}`],{allowFailure:!0});if(a.exitCode!==0)return{installed:!0};let o=a.stdout.toLowerCase();return{installed:!0,simulatorCompatible:o.includes(`iossimulator`)||o.includes(`platform 7`)}}function Qe(e){return e.installed?e.simulatorCompatible===!1?`ARCH_MISMATCH`:`PERSISTENT_LAUNCH_FAIL`:`APP_NOT_INSTALLED`}function $e(e){switch(e){case`ARCH_MISMATCH`:return`The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.`;case`APP_NOT_INSTALLED`:return`The app bundle is not installed on this simulator. Run install before open.`;case`PERSISTENT_LAUNCH_FAIL`:return`The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.`;default:return`The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details.`}}const Y=25e3;async function et(e,n,r){let i=r?.launchConsole?.trim(),a=r?.launchArgs;if(i&&(!l(e)||e.kind!==`simulator`))throw new t(`UNSUPPORTED_OPERATION`,ee);if(u(e)){if(a&&a.length>0)throw new t(`UNSUPPORTED_OPERATION`,`--launch-args is not supported on macOS; launch arguments are currently iOS-only.`);await Se(e,n,r);return}let f=r?.url?.trim();if(f){if(i)throw new t(`INVALID_ARGS`,d);if(!c(f))throw new t(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);if(e.kind===`simulator`){let t=!!a||o(f);if(r?.terminateRunningApp||t){let i=r?.appBundleId??await j(e,n);t?await rt(e,i,{...a?{launchArgs:a}:{},...r?.terminateRunningApp?{terminateRunningApp:!0}:{}}):await nt(e,i)}await X(e,f,void 0);return}let l=s(r?.appBundleId??await j(e,n),f);if(!l)throw new t(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await Q(e,l,{payloadUrl:f,launchArgs:a,runnerOptions:r?.runnerOptions});return}let p=n.trim();if(c(p)){if(i)throw new t(`INVALID_ARGS`,d);if(e.kind===`simulator`){await X(e,p,a);return}let n=s(r?.appBundleId,p);if(!n)throw new t(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await Q(e,n,{payloadUrl:p,launchArgs:a,runnerOptions:r?.runnerOptions});return}let m=r?.appBundleId??await j(e,n);if(e.kind===`simulator`){await rt(e,m,{...i?{launchConsole:i}:{},...a?{launchArgs:a}:{},...r?.terminateRunningApp?{terminateRunningApp:!0}:{}});return}await Q(e,m,{launchArgs:a,runnerOptions:r?.runnerOptions})}async function X(e,n,r){if(r&&r.length>0)throw new t(`INVALID_ARGS`,`--launch-args is not supported with iOS simulator URL opens (simctl openurl ignores launch args). Launch the app first with --launch-args, then issue the URL open in a separate call.`);await k(e),await S(e,[`openurl`,e.id,n])}async function tt(e){u(e)||e.kind===`simulator`&&await _e(e)!==`Booted`&&await k(e)}async function Z(e,t,n){if(u(e)){await ye(e,t);return}let r=await j(e,t);if(e.kind===`simulator`){await nt(e,r);return}await x(e).terminateApp(e,r,{runnerOptions:n,runRunnerCommand:D})}async function nt(e,n){await k(e);let r=C(e,[`terminate`,e.id,n]),i=await T(r,{allowFailure:!0,timeoutMs:pe});if(i.exitCode!==0&&!i.stderr.toLowerCase().includes(`found nothing to terminate`))throw new t(`COMMAND_FAILED`,`xcrun exited with code ${i.exitCode}`,p(i,{cmd:`xcrun`,args:r}))}async function rt(e,n,r){await k(e);let i=0,a=g.fromTimeoutMs(de);try{await _(async({deadline:i})=>{if(i?.isExpired())throw new t(`COMMAND_FAILED`,`App launch deadline exceeded`,{timeoutMs:de});let a=C(e,it(e.id,n,r)),o=r?.launchConsole?await at(a,r.launchConsole):await T(a,{allowFailure:!0});if(o.exitCode!==0)throw new t(`COMMAND_FAILED`,`xcrun exited with code ${o.exitCode}`,p(o,{cmd:`xcrun`,args:a}))},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry(e){return J(e)?(i+=1,i<3):!1}},{deadline:a})}catch(t){if(J(t)){let r=t,i=Qe(await Ze(e,n));r.details={...r.details,hint:$e(i)}}throw t}}function it(e,t,n){let r=[`launch`];return n?.launchConsole&&r.push(`--console-pty`),n?.terminateRunningApp&&r.push(`--terminate-running-process`),r.push(e,t),n?.launchArgs&&n.launchArgs.length>0&&r.push(...n.launchArgs),r}async function at(e,n){await N.mkdir(M.dirname(n),{recursive:!0});try{let t=await T(e,{allowFailure:!0,timeoutMs:Y});return await ot(n,t.stdout,t.stderr),t}catch(e){let r=(e instanceof t?e:void 0)?.details;if(r?.timeoutMs===Y){let e=typeof r.stdout==`string`?r.stdout:``,t=typeof r.stderr==`string`?r.stderr:``;return await ot(n,e,t),h({level:`warn`,phase:`ios_simulator_launch_console_capture_timeout`,data:{timeoutMs:Y,logPath:n,stdoutBytes:Buffer.byteLength(e),stderrBytes:Buffer.byteLength(t)}}),{stdout:e,stderr:t,exitCode:0}}throw e}}async function ot(e,t,n){await N.writeFile(e,st(t,n),`utf8`)}function st(e,t){return!e||!t||e.endsWith(`
|
|
3
|
-
`)||e.endsWith(`\r`)?`${e}${t}`:`${e}\n${t}`}async function Q(e,t,n){await
|
|
4
|
-
`).replace(/\n$/,``))}async function
|
|
5
|
-
`)){let e=r.trim();if(!e)continue;if(e===`service`){n=!0;continue}if(!n)continue;if(e.startsWith(`bundle identifier`))break;let i=/^([a-z-]+)\s+-\s+/.exec(e)?.[1];i!==void 0&&t.add(i)}return t}function
|
|
1
|
+
import{n as e}from"./rolldown-runtime.js";import{_ as t}from"./sdk-contracts.js";import{a as n,c as r,n as i,s as a}from"./location-coordinates.js";import{J as o,K as s,X as c,Y as l,q as u}from"./sdk-batch-runner.js";import{c as d,l as f}from"./sdk-device.js";import"./observability.js";import{A as p,f as m,h}from"./sdk-android-adb.js";import{i as g,o as ee}from"./boot-diagnostics.js";import{n as te,t as _}from"./setting-state.js";import{t as ne}from"./appearance.js";import{n as re,r as ie,s as ae}from"./simctl.js";import{t as oe}from"./png-resize.js";import{i as se,n as ce}from"./screenshot-density.js";import{a as v,i as y}from"./tool-provider.js";import{a as b,i as x,l as le,n as S,o as C,r as w}from"./physical-device-control.js";import{a as T,c as ue,d as de,f as fe,l as pe,t as E,u as me}from"./config.js";import{n as D}from"./runner-client.js";import{n as he,r as O,t as k}from"./simulator.js";import{i as ge}from"./helper.js";import{a as _e,c as ve,i as A,l as ye,n as be,o as xe,r as Se,s as Ce,u as we}from"./app-resolution.js";import j from"node:path";import{promises as M}from"node:fs";import"node:os";const Te=[`--time`,`9:41`,`--dataNetwork`,`wifi`,`--wifiMode`,`active`,`--wifiBars`,`3`,`--batteryState`,`charged`,`--batteryLevel`,`100`],Ee={0:`hide`,1:`wifi`,6:`3g`,7:`4g`,8:`lte`,9:`lte-a`,10:`lte+`,11:`5g`,12:`5g+`,13:`5g-uwb`,14:`5g-uc`},De={1:`searching`,2:`failed`,3:`active`},Oe={0:`notSupported`,1:`searching`,2:`failed`,3:`active`};function N(e,t,n){return ie(e,t,n)}const P=new Set;async function ke(e){let t=null,n=!1;if(Me(e))n=!0;else try{t=await Ne(e),n=!0}catch(t){R(e,`snapshot_failed`,t)}try{(!n||t)&&await Pe(e),await L(e,Te)}catch(t){R(e,`prepare_failed`,t)}return async()=>{await Ae(e,n?t:null)}}async function Ae(e,t){if(await Pe(e),!t){je(e);return}await L(e,Ie(t)),F(e)}function F(e){P.delete(I(e))}function je(e){P.add(I(e))}function Me(e){return P.has(I(e))}function I(e){return`${e.platform}:${e.kind}:${e.id}`}async function Ne(e){return Fe(h(await N(e,[`status_bar`,e.id,`list`],{allowFailure:!0}),`Failed to read simulator status bar overrides`).stdout)}async function Pe(e){await N(e,[`status_bar`,e.id,`clear`])}async function L(e,t){t.length!==0&&await N(e,[`status_bar`,e.id,`override`,...t])}function Fe(e){let n={},r=e.split(`
|
|
2
|
+
`).map(e=>e.trim()).filter(e=>e.length>0&&e!==`Current Status Bar Overrides:`&&!/^=+$/.test(e));for(let e of r){let r=/^DataNetworkType:\s+(\d+)$/.exec(e);if(r){let e=Number(r[1]),i=Ee[e];if(!i)throw new t(`COMMAND_FAILED`,`Unsupported simulator data network type: ${e}`);n.dataNetwork=i;continue}let i=/^WiFi Mode:\s+(\d+),\s+WiFi Bars:\s+(\d+)$/.exec(e);if(i){let e=De[Number(i[1])];e&&(n.wifiMode=e),n.wifiBars=i[2];continue}let a=/^Cell Mode:\s+(\d+),\s+Cell Bars:\s+(\d+)$/.exec(e);if(a){let e=Number(a[1]),r=Oe[e];if(!r)throw new t(`COMMAND_FAILED`,`Unsupported simulator cellular mode: ${e}`);n.cellularMode=r,n.cellularBars=a[2];continue}let o=/^Operator Name:\s*(.*)$/.exec(e);if(o){n.operatorName=o[1]??``;continue}}return Object.keys(n).length===0?null:n}function Ie(e){let t=[];return e.dataNetwork&&t.push(`--dataNetwork`,e.dataNetwork),e.wifiMode&&t.push(`--wifiMode`,e.wifiMode),e.wifiBars!==void 0&&(e.dataNetwork===`wifi`||e.wifiMode)&&t.push(`--wifiBars`,e.wifiBars),e.cellularMode&&t.push(`--cellularMode`,e.cellularMode),e.cellularBars!==void 0&&(e.cellularMode||Le(e.dataNetwork)||e.operatorName!==void 0)&&t.push(`--cellularBars`,e.cellularBars),e.operatorName!==void 0&&t.push(`--operatorName`,e.operatorName),t}function Le(e){return!!(e&&e!==`hide`&&e!==`wifi`)}function R(e,t,n){p({level:`warn`,phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...x(n)}})}function z(e,t,n){return ie(e,t,n)}const Re={ensureBooted:k,prepareStatusBarForScreenshot:ke,captureWithRetry:Ve,normalizeDensity:qe,captureWithRunner:H,shouldFallbackToRunner:G},B=new Map,V=new Map;async function ze(e,t,n={}){if(f(e)){await H(e,t,n.appBundleId,n.fullscreen,n.runnerOptions);return}if(e.kind===`simulator`){await Be(e,t,n);return}await S(e).captureScreenshot(e,t,{appBundleId:n.appBundleId,fullscreen:n.fullscreen,runnerOptions:n.runnerOptions,runRunnerCommand:D})}async function Be(e,n,r={}){if(e.kind!==`simulator`)throw new t(`UNSUPPORTED_OPERATION`,`Simulator screenshot fallback flow supports only iOS simulators`);let i={...Re,...r.deps??{}};r.skipIosSimulatorBootCheck||await i.ensureBooted(e);let a=async()=>{};if(r.normalizeStatusBar===!0)try{a=await i.prepareStatusBarForScreenshot(e)}catch(t){W(e,`prepare_failed`,t)}try{try{await i.captureWithRetry(e,n),await i.normalizeDensity(e,n,r.pixelDensity);return}catch(t){let a=t;if(r.skipIosSimulatorBootCheck&&Ke(t)){await i.ensureBooted(e);try{await i.captureWithRetry(e,n),await i.normalizeDensity(e,n,r.pixelDensity);return}catch(e){a=e}}if(!i.shouldFallbackToRunner(a))throw a;We(e,`simctl_screenshot`,a)}await i.captureWithRunner(e,n,r.appBundleId,r.fullscreen,r.runnerOptions),await i.normalizeDensity(e,n,r.pixelDensity)}finally{await a().catch(t=>W(e,`restore_failed`,t))}}async function Ve(e,t){let n=g.fromTimeoutMs(de);await ee(async({deadline:n})=>{await z(e,[`io`,e.id,`screenshot`,t],{timeoutMs:Math.max(1e3,n?.remainingMs()??2e4)})},{maxAttempts:5,baseDelayMs:ue,maxDelayMs:pe,jitter:.2,shouldRetry:e=>G(e)},{deadline:n,phase:`ios_simulator_screenshot`})}async function H(e,n,r,i,a){if(e.kind===`device`&&!f(e)){await S(e).captureScreenshot(e,n,{appBundleId:r,fullscreen:i,runnerOptions:a,preferRunner:!0,runRunnerCommand:D});return}let o=(await D(e,{command:`screenshot`,appBundleId:r,fullscreen:i,inlineScreenshot:!1},a)).message;if(!o)throw new t(`COMMAND_FAILED`,`Failed to capture iOS screenshot: runner returned no file path`);if(f(e)){await M.copyFile(o,n);return}if(e.kind===`simulator`){await He(e,o,n);return}throw new t(`COMMAND_FAILED`,`Unsupported Apple screenshot target`)}async function He(e,n,r){let i=g.fromTimeoutMs(T),a=`Unable to locate runner container for simulator screenshot`,o=V.get(e.id);if(o){let t=await U(o,n,r);if(t.copied)return;a=t.error,V.delete(e.id)}for(let t of le){let o=await z(e,[`get_app_container`,e.id,t,`data`],{allowFailure:!0,timeoutMs:Ue(i,T,`runner screenshot container lookup`)});if(o.exitCode!==0){let e=o.stderr.trim();e&&(a=e);continue}let s=o.stdout.trim();if(!s){a=`simctl get_app_container returned empty output`;continue}let c=await U(s,n,r);if(c.copied){V.set(e.id,s);return}a=c.error}throw new t(`COMMAND_FAILED`,`Failed to capture iOS screenshot: ${a}`)}async function U(e,t,n){let r=`Runner screenshot was not found in the simulator container`;for(let i of Ge(e,t))try{return await M.copyFile(i,n),{copied:!0}}catch(e){r=e instanceof Error?e.message:String(e)}return{copied:!1,error:r}}function Ue(e,n,r){let i=e.remainingMs();if(i>0)return i;throw new t(`COMMAND_FAILED`,`iOS ${r} timed out after ${n}ms`,{timeoutMs:n,step:r})}function We(e,t,n){let r=x(n);p({level:`warn`,phase:`ios_screenshot_fallback`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:`runner`,...r}})}function W(e,t,n){p({level:`warn`,phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...x(n)}})}function Ge(e,t){let n=j.resolve(e),r=t.trim();if(!r)return[];let i=[],a=new Set,o=e=>{let t=j.normalize(e);a.has(t)||(a.add(t),i.push(t))},s=r.replace(/^\/+/,``),c=s.replace(/\\/g,`/`);if(s&&o(j.join(n,s)),j.isAbsolute(r)&&o(j.normalize(r)),c.startsWith(`tmp/`))o(j.join(n,c));else{let e=c.lastIndexOf(`/tmp/`);if(e>=0){let t=c.slice(e+1);o(j.join(n,t))}}let l=j.basename(r);return l&&o(j.join(n,`tmp`,l)),i}function G(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=w(e);return n.includes(`timeout waiting for screen surfaces`)||n.includes(`nsposixerrordomain`)&&n.includes(`code=60`)&&n.includes(`screenshot`)||n.includes(`timed out`)&&n.includes(`screenshot`)}function Ke(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=w(e);return n.includes(`not booted`)||n.includes(`current state: shutdown`)||n.includes(`current state is shutdown`)||n.includes(`current state=shutdown`)||n.includes(`state: shutdown`)||n.includes(`state=shutdown`)}async function qe(e,t,n){let r=await Je(e),i=ce(await se(t),r,n);i&&await oe(t,i.width,i.height)}async function Je(e){let n=B.get(e.id);if(n!==void 0)return n;let r=await z(e,[`getenv`,e.id,`SIMULATOR_MAINSCREEN_SCALE`],{timeoutMs:me}),i=Number(r.stdout.trim());if(!Number.isFinite(i)||i<=0)throw new t(`COMMAND_FAILED`,`Failed to read iOS simulator screenshot scale from SIMULATOR_MAINSCREEN_SCALE`);return B.set(e.id,i),i}function K(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=e.details??{};if(n.exitCode!==4)return!1;let r=String(n.stderr??``).toLowerCase();return r.includes(`fbsopenapplicationserviceerrordomain`)&&r.includes(`the request to open`)}async function Ye(e,t){let n=await v(re(e,[`get_app_container`,e.id,t]),{allowFailure:!0});if(n.exitCode!==0)return{installed:!1};let r=n.stdout.trim();if(!r)return{installed:!1};let i=await y(`plutil`,[`-extract`,`CFBundleExecutable`,`raw`,`-o`,`-`,`${r}/Info.plist`],{allowFailure:!0});if(i.exitCode!==0||!i.stdout.trim())return{installed:!0};let a=await y(`otool`,[`-l`,`${r}/${i.stdout.trim()}`],{allowFailure:!0});if(a.exitCode!==0)return{installed:!0};let o=a.stdout.toLowerCase();return{installed:!0,simulatorCompatible:o.includes(`iossimulator`)||o.includes(`platform 7`)}}function Xe(e){return e.installed?e.simulatorCompatible===!1?`ARCH_MISMATCH`:`PERSISTENT_LAUNCH_FAIL`:`APP_NOT_INSTALLED`}function Ze(e){switch(e){case`ARCH_MISMATCH`:return`The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.`;case`APP_NOT_INSTALLED`:return`The app bundle is not installed on this simulator. Run install before open.`;case`PERSISTENT_LAUNCH_FAIL`:return`The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.`;default:return`The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details.`}}const q=25e3;async function Qe(e,n,r){let i=r?.launchConsole?.trim(),a=r?.launchArgs;if(i&&(!d(e)||e.kind!==`simulator`))throw new t(`UNSUPPORTED_OPERATION`,u);if(f(e)){if(a&&a.length>0)throw new t(`UNSUPPORTED_OPERATION`,`--launch-args is not supported on macOS; launch arguments are currently iOS-only.`);await Ce(e,n,r);return}let p=r?.url?.trim();if(p){if(i)throw new t(`INVALID_ARGS`,s);if(!o(p))throw new t(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);if(e.kind===`simulator`){let t=!!a||l(p);if(r?.terminateRunningApp||t){let i=r?.appBundleId??await A(e,n);t?await Z(e,i,{...a?{launchArgs:a}:{},...r?.terminateRunningApp?{terminateRunningApp:!0}:{}}):await X(e,i)}await J(e,p,void 0);return}let u=c(r?.appBundleId??await A(e,n),p);if(!u)throw new t(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await Q(e,u,{payloadUrl:p,launchArgs:a,runnerOptions:r?.runnerOptions});return}let m=n.trim();if(o(m)){if(i)throw new t(`INVALID_ARGS`,s);if(e.kind===`simulator`){await J(e,m,a);return}let n=c(r?.appBundleId,m);if(!n)throw new t(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await Q(e,n,{payloadUrl:m,launchArgs:a,runnerOptions:r?.runnerOptions});return}let h=r?.appBundleId??await A(e,n);if(e.kind===`simulator`){await Z(e,h,{...i?{launchConsole:i}:{},...a?{launchArgs:a}:{},...r?.terminateRunningApp?{terminateRunningApp:!0}:{}});return}await Q(e,h,{launchArgs:a,runnerOptions:r?.runnerOptions})}async function J(e,n,r){if(r&&r.length>0)throw new t(`INVALID_ARGS`,`--launch-args is not supported with iOS simulator URL opens (simctl openurl ignores launch args). Launch the app first with --launch-args, then issue the URL open in a separate call.`);await k(e),await b(e,[`openurl`,e.id,n])}async function $e(e){f(e)||e.kind===`simulator`&&await he(e)!==`Booted`&&await k(e)}async function Y(e,t,n){if(f(e)){await xe(e,t);return}let r=await A(e,t);if(e.kind===`simulator`){await X(e,r);return}await S(e).terminateApp(e,r,{runnerOptions:n,runRunnerCommand:D})}async function X(e,n){await k(e);let r=C(e,[`terminate`,e.id,n]),i=await v(r,{allowFailure:!0,timeoutMs:fe});if(i.exitCode!==0&&!i.stderr.toLowerCase().includes(`found nothing to terminate`))throw new t(`COMMAND_FAILED`,`xcrun exited with code ${i.exitCode}`,m(i,{cmd:`xcrun`,args:r}))}async function Z(e,n,r){await k(e);let i=0,a=g.fromTimeoutMs(E);try{await ee(async({deadline:i})=>{if(i?.isExpired())throw new t(`COMMAND_FAILED`,`App launch deadline exceeded`,{timeoutMs:E});let a=C(e,et(e.id,n,r)),o=r?.launchConsole?await tt(a,r.launchConsole):await v(a,{allowFailure:!0});if(o.exitCode!==0)throw new t(`COMMAND_FAILED`,`xcrun exited with code ${o.exitCode}`,m(o,{cmd:`xcrun`,args:a}))},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry(e){return K(e)?(i+=1,i<3):!1}},{deadline:a})}catch(t){if(K(t)){let r=t,i=Xe(await Ye(e,n));r.details={...r.details,hint:Ze(i)}}throw t}}function et(e,t,n){let r=[`launch`];return n?.launchConsole&&r.push(`--console-pty`),n?.terminateRunningApp&&r.push(`--terminate-running-process`),r.push(e,t),n?.launchArgs&&n.launchArgs.length>0&&r.push(...n.launchArgs),r}async function tt(e,n){await M.mkdir(j.dirname(n),{recursive:!0});try{let t=await v(e,{allowFailure:!0,timeoutMs:q});return await nt(n,t.stdout,t.stderr),t}catch(e){let r=(e instanceof t?e:void 0)?.details;if(r?.timeoutMs===q){let e=typeof r.stdout==`string`?r.stdout:``,t=typeof r.stderr==`string`?r.stderr:``;return await nt(n,e,t),p({level:`warn`,phase:`ios_simulator_launch_console_capture_timeout`,data:{timeoutMs:q,logPath:n,stdoutBytes:Buffer.byteLength(e),stderrBytes:Buffer.byteLength(t)}}),{stdout:e,stderr:t,exitCode:0}}throw e}}async function nt(e,t,n){await M.writeFile(e,rt(t,n),`utf8`)}function rt(e,t){return!e||!t||e.endsWith(`
|
|
3
|
+
`)||e.endsWith(`\r`)?`${e}${t}`:`${e}\n${t}`}async function Q(e,t,n){await S(e).launchApp(e,t,{...n,runRunnerCommand:D})}async function it(e){return f(e)?await ve():(O(e,`clipboard`),await k(e),h(await b(e,[`pbpaste`,e.id],{allowFailure:!0}),`Failed to read iOS simulator clipboard`).stdout.replace(/\r\n/g,`
|
|
4
|
+
`).replace(/\n$/,``))}async function at(e,t){if(f(e)){await we(t);return}O(e,`clipboard`),await k(e),h(await b(e,[`pbcopy`,e.id],{allowFailure:!0,stdin:t}),`Failed to write iOS simulator clipboard`)}let $=null,ot;async function st(e,r,o,s,c){if(f(e)){let e=r.toLowerCase();if(e===`appearance`){await ye(o);return}if(e===`permission`){let e=a(o);if(e===`deny`)throw new t(`INVALID_ARGS`,n(`permission`));return await ge(e,lt(c?.permissionTarget))}throw new t(`INVALID_ARGS`,n(r))}O(e,`settings`),await k(e);let l=r.toLowerCase();switch(l){case`clear-app-state`:{if(o.toLowerCase()!==`clear`)throw new t(`INVALID_ARGS`,`settings clear-app-state only supports clear.`);if(!s)throw new t(`INVALID_ARGS`,`settings clear-app-state requires an app id or an active app session.`);let n=await ct(e,s);return{bundleId:n.bundleId,containerPath:n.containerPath,cleared:!0}}case`wifi`:{let t=_(o)?`active`:`failed`;await b(e,[`status_bar`,e.id,`override`,`--wifiMode`,t]),F(e);return}case`airplane`:_(o)?(await b(e,[`status_bar`,e.id,`override`,`--dataNetwork`,`hide`,`--wifiMode`,`failed`,`--wifiBars`,`0`,`--cellularMode`,`failed`,`--cellularBars`,`0`,`--operatorName`,``]),F(e)):(await b(e,[`status_bar`,e.id,`clear`]),je(e));return;case`location`:{if(o.toLowerCase()===`set`){let{latitude:t,longitude:n}=i(c);return await b(e,[`location`,e.id,`set`,`${t},${n}`]),{latitude:t,longitude:n}}let n=_(o);if(!s)throw new t(`INVALID_ARGS`,`location setting requires an active app in session`);let r=n?`grant`:`revoke`;await b(e,[`privacy`,e.id,r,`location`,s]);return}case`faceid`:case`touchid`:{let t=l,n=ft[t];await bt(e,yt(o,t),{settingName:t,label:n.label,modalityAliases:n.modalityAliases});return}case`appearance`:{let t=await ut(e,o);await b(e,[`ui`,e.id,`appearance`,t]);return}case`permission`:if(!s)throw new t(`INVALID_ARGS`,`permission setting requires an active app in session`);await mt(e,pt(a(o)),vt(c?.permissionTarget,c?.permissionMode),s);return;default:throw new t(`INVALID_ARGS`,`Unsupported setting: ${r}`)}}async function ct(e,n){if(!d(e)||e.kind!==`simulator`)throw new t(`UNSUPPORTED_OPERATION`,`Clearing app state is currently supported only on iOS simulators.`);let r=await A(e,n);await k(e),await Y(e,r);let i=h(await b(e,[`get_app_container`,e.id,r,`data`],{allowFailure:!0}),`simctl get_app_container failed for ${r}`).stdout.trim();if(!i)throw new t(`COMMAND_FAILED`,`simctl get_app_container returned an empty data container path for ${r}`);let a=await M.readdir(i);return await Promise.all(a.map(e=>M.rm(j.join(i,e),{recursive:!0,force:!0}))),{bundleId:r,containerPath:i}}function lt(e){let n=e?.trim().toLowerCase();if(n===`accessibility`||n===`screen-recording`||n===`input-monitoring`)return n;throw new t(`INVALID_ARGS`,`Unsupported macOS permission target. Use accessibility|screen-recording|input-monitoring.`)}async function ut(e,n){let r=ne(n);if(r!==`toggle`)return r;let i=h(await b(e,[`ui`,e.id,`appearance`],{allowFailure:!0}),`Failed to read current iOS appearance`),a=dt(i.stdout,i.stderr);if(!a)throw new t(`COMMAND_FAILED`,`Unable to determine current iOS appearance for toggle`,{stdout:i.stdout,stderr:i.stderr});return a===`dark`?`light`:`dark`}function dt(e,t){let n=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}\n${t}`);if(!n)return null;let r=n[1]?.toLowerCase();return r===`dark`?`dark`:r===`light`?`light`:null}const ft={faceid:{label:`Face ID`,modalityAliases:[`face`]},touchid:{label:`Touch ID`,modalityAliases:[`finger`,`touch`]}};function pt(e){return e===`deny`?`revoke`:e}async function mt(e,n,r,i){let a=await gt(e);if(!a.has(r))throw new t(`UNSUPPORTED_OPERATION`,`iOS simctl privacy does not support service "${r}" on this runtime.`,{deviceId:e.id,appBundleId:i,hint:`Supported services: ${Array.from(a).sort().join(`, `)}`});let o=[`privacy`,e.id,n,r,i],s=r===`notifications`;if(!(n===`reset`&&s))try{await b(e,o);return}catch(n){throw s&&ht(n)?new t(`UNSUPPORTED_OPERATION`,`iOS simulator does not support setting notifications permission via simctl privacy on this runtime.`,{deviceId:e.id,appBundleId:i,hint:`Use reset notifications for reprompt behavior, or toggle notifications manually in Settings.`}):n}try{await b(e,o);return}catch(e){if(!ht(e))throw e}try{await b(e,[`privacy`,e.id,`reset`,`all`,i])}catch(n){throw new t(`COMMAND_FAILED`,`iOS simulator blocked direct notifications reset. Fallback reset-all also failed.`,{deviceId:e.id,appBundleId:i,hint:`Use reinstall to force a fresh notifications prompt, or reset simulator content and settings.`},n instanceof Error?n:void 0)}}function ht(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=String(e.details?.stderr??``).toLowerCase();return(n.includes(`failed to grant access`)||n.includes(`failed to revoke access`)||n.includes(`failed to reset access`))&&n.includes(`operation not permitted`)}async function gt(e){let n=ae(e.simulatorSetPath),r=`${process.env.PATH??``}::${n??``}`;if($&&ot===r)return $;let i=await b(e,[`privacy`,`help`],{allowFailure:!0}),a=_t(`${i.stdout}\n${i.stderr}`);if(a.size===0)throw new t(`COMMAND_FAILED`,`Unable to determine supported simctl privacy services`,{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode,hint:"Run `xcrun simctl privacy help` manually to verify available services for this runtime."});return $=a,ot=r,a}function _t(e){let t=new Set,n=!1;for(let r of e.split(`
|
|
5
|
+
`)){let e=r.trim();if(!e)continue;if(e===`service`){n=!0;continue}if(!n)continue;if(e.startsWith(`bundle identifier`))break;let i=/^([a-z-]+)\s+-\s+/.exec(e)?.[1];i!==void 0&&t.add(i)}return t}function vt(e,n){let i=r(e);if(i!==`photos`&&n?.trim())throw new t(`INVALID_ARGS`,`Permission mode is only supported for photos. Received: ${n}.`);if(i===`camera`)return`camera`;if(i===`microphone`)return`microphone`;if(i===`contacts`)return`contacts`;if(i===`contacts-limited`)return`contacts-limited`;if(i===`notifications`)return`notifications`;if(i===`calendar`)return`calendar`;if(i===`location`)return`location`;if(i===`location-always`)return`location-always`;if(i===`media-library`)return`media-library`;if(i===`motion`)return`motion`;if(i===`reminders`)return`reminders`;if(i===`siri`)return`siri`;if(i===`photos`){let e=n?.trim().toLowerCase();if(!e||e===`full`)return`photos`;if(e===`limited`)return`photos-add`;throw new t(`INVALID_ARGS`,`Invalid photos mode: ${n}. Use full|limited.`)}throw new t(`INVALID_ARGS`,`Unsupported permission target: ${e}. Use camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri.`)}function yt(e,n){let r=e.trim().toLowerCase();if(r===`match`)return`match`;if(r===`nonmatch`)return`nonmatch`;if(r===`enroll`)return`enroll`;if(r===`unenroll`)return`unenroll`;throw new t(`INVALID_ARGS`,`Invalid ${n} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}async function bt(e,n,r){let i=xt(e.id,n,r.modalityAliases),a=[];for(let t of i){let n=C(e,t),r=await v(n,{allowFailure:!0});if(r.exitCode===0)return;a.push({args:n,stderr:r.stderr,stdout:r.stdout,exitCode:r.exitCode})}let o=te(a);throw a.length>0&&a.every(e=>St(e.stdout,e.stderr))?new t(`UNSUPPORTED_OPERATION`,`${r.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:n,setting:r.settingName,attempts:o}):new t(`COMMAND_FAILED`,`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:n,setting:r.settingName,attempts:o})}function xt(e,t,n){let r=n.length>0?n:[`face`];switch(t){case`match`:return r.flatMap(t=>[[`biometric`,e,`match`,t],[`biometric`,`match`,e,t]]);case`nonmatch`:return r.flatMap(t=>[[`biometric`,e,`nonmatch`,t],[`biometric`,e,`nomatch`,t],[`biometric`,`nonmatch`,e,t],[`biometric`,`nomatch`,e,t]]);case`enroll`:return[[`biometric`,e,`enroll`,`yes`],[`biometric`,e,`enroll`,`1`],[`biometric`,`enroll`,e,`yes`],[`biometric`,`enroll`,e,`1`]];case`unenroll`:return[[`biometric`,e,`enroll`,`no`],[`biometric`,e,`enroll`,`0`],[`biometric`,`enroll`,e,`no`],[`biometric`,`enroll`,e,`0`]]}}function St(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`unrecognized subcommand`)||n.includes(`unknown subcommand`)||n.includes(`not supported`)||n.includes(`unavailable`)||n.includes(`biometric`)&&n.includes(`invalid`)}var Ct=e({findIosSimulatorInstalledApp:()=>be,listIosApps:()=>Se,resolveIosApp:()=>A,resolveIosSimulatorDeepLinkBundleId:()=>_e});export{Y as a,H as c,at as i,ze as l,st as n,Qe as o,it as r,$e as s,Ct as t};
|
package/dist/src/artifacts.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
//#region src/platforms/android/manifest.d.ts
|
|
2
|
-
declare function resolveAndroidArchivePackageName(archivePath: string): Promise<string | undefined>;
|
|
2
|
+
declare function resolveAndroidArchivePackageName(archivePath: string, signal?: AbortSignal): Promise<string | undefined>;
|
|
3
3
|
//#endregion
|
|
4
4
|
export { resolveAndroidArchivePackageName };
|
package/dist/src/audio-probe.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as e}from"./sdk-device.js";import{
|
|
1
|
+
import{c as e}from"./sdk-device.js";import{o as t}from"./helper.js";const n={platform:`host-system-audio`,source:`system-audio`,backend:`macos-screencapturekit`,sourceCount:1,start:t,notes:r};function r(t){return[`Audio probe samples host system audio through ScreenCaptureKit for this ${e(t)?`iOS simulator`:t.platform===`android`?`Android emulator`:`macOS session`}; it is not app-instrumented audio.`,`Screen Recording permission is required for host system audio capture.`,`Other audible host apps can contribute to the measured buckets.`]}export{n as macOsScreenCaptureKitAudioProbeBackend};
|