@phone-use/sdk 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +85 -2
- package/dist/index.mjs +137 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/backends/cloud-sandbox.ts +226 -0
- package/src/backends/device-runner.ts +2 -0
- package/src/index.ts +16 -2
package/dist/index.d.mts
CHANGED
|
@@ -477,6 +477,87 @@ declare function executeAction(core: DeviceCore, action: Action, opts?: ActOptio
|
|
|
477
477
|
*/
|
|
478
478
|
declare function createAgentDeviceBackend(config?: DeviceConfig): DeviceBackend;
|
|
479
479
|
//#endregion
|
|
480
|
+
//#region src/backends/cloud-sandbox.d.ts
|
|
481
|
+
/** Every device verb a cloud sandbox accepts over the RPC wire. The worker's
|
|
482
|
+
* runtime set is contract-tested against this union. */
|
|
483
|
+
type SandboxRpcMethod = 'snapshot' | 'screenshot' | 'press' | 'longPress' | 'fill' | 'typeText' | 'pressKey' | 'scroll' | 'pan' | 'installApp' | 'waitForText' | 'systemAlert' | 'home' | 'back' | 'openApp' | 'listApps' | 'closeSession';
|
|
484
|
+
/** Body of `POST <endpoint>/rpc`: one verb and its positional arguments. */
|
|
485
|
+
type SandboxRpcRequest = {
|
|
486
|
+
method: SandboxRpcMethod;
|
|
487
|
+
args: unknown[];
|
|
488
|
+
};
|
|
489
|
+
/** RPC completed; `result` is the verb-specific payload. */
|
|
490
|
+
type SandboxRpcSuccess = {
|
|
491
|
+
ok: true;
|
|
492
|
+
result: unknown;
|
|
493
|
+
};
|
|
494
|
+
/** RPC failed on-device. `code` is a stable taxonomy bucket (`device_gone`,
|
|
495
|
+
* `timeout`, `session_conflict`, `target_not_found`, `internal`) and
|
|
496
|
+
* `retryable` tells agents whether retrying may succeed. */
|
|
497
|
+
type SandboxRpcFailure = {
|
|
498
|
+
ok: false;
|
|
499
|
+
error: {
|
|
500
|
+
message: string;
|
|
501
|
+
code?: string | undefined;
|
|
502
|
+
retryable?: boolean | undefined;
|
|
503
|
+
};
|
|
504
|
+
};
|
|
505
|
+
/** Discriminated RPC outcome — branch on `ok`. */
|
|
506
|
+
type SandboxRpcResponse = SandboxRpcSuccess | SandboxRpcFailure;
|
|
507
|
+
/** Connection settings for one provisioned cloud phone: the per-sandbox
|
|
508
|
+
* `endpoint`/`token` pair returned by `phone-use create` (or `/v1/sandboxes`). */
|
|
509
|
+
type CloudSandboxBackendOptions = {
|
|
510
|
+
endpoint: string;
|
|
511
|
+
token: string;
|
|
512
|
+
capabilities?: Capability[] | undefined;
|
|
513
|
+
fetch?: typeof globalThis.fetch | undefined;
|
|
514
|
+
};
|
|
515
|
+
declare class CloudSandboxBackend extends BaseDeviceBackend {
|
|
516
|
+
private readonly endpoint;
|
|
517
|
+
private readonly token;
|
|
518
|
+
private readonly fetchImpl;
|
|
519
|
+
constructor(opts: CloudSandboxBackendOptions);
|
|
520
|
+
private rpc;
|
|
521
|
+
snapshot(opts?: {
|
|
522
|
+
interactiveOnly?: boolean;
|
|
523
|
+
depth?: number;
|
|
524
|
+
}): Promise<Snapshot>;
|
|
525
|
+
screenshot(opts: {
|
|
526
|
+
path: string;
|
|
527
|
+
overlayRefs?: boolean;
|
|
528
|
+
}): Promise<{
|
|
529
|
+
path: string;
|
|
530
|
+
}>;
|
|
531
|
+
press(target: PressTarget): Promise<void>;
|
|
532
|
+
longPress(ref: string, durationMs?: number): Promise<void>;
|
|
533
|
+
fill(ref: string, text: string): Promise<void>;
|
|
534
|
+
typeText(text: string): Promise<void>;
|
|
535
|
+
pressKey(key: 'return'): Promise<void>;
|
|
536
|
+
scroll(direction: ScrollDirection): Promise<void>;
|
|
537
|
+
pan(x: number, y: number, dx: number, dy: number, durationMs?: number): Promise<void>;
|
|
538
|
+
waitForText(text: string, timeoutMs?: number): Promise<void>;
|
|
539
|
+
systemAlert(action: AlertAction): Promise<BackendAlertResult>;
|
|
540
|
+
home(): Promise<void>;
|
|
541
|
+
back(): Promise<void>;
|
|
542
|
+
openApp(opts: {
|
|
543
|
+
app?: string;
|
|
544
|
+
url?: string;
|
|
545
|
+
relaunch?: boolean;
|
|
546
|
+
}): Promise<OpenAppResult>;
|
|
547
|
+
listApps(): Promise<string[]>;
|
|
548
|
+
closeSession(): Promise<void>;
|
|
549
|
+
/** Upload a zipped .app bundle (base64) and install it on the sandbox device. */
|
|
550
|
+
installApp(base64Zip: string): Promise<{
|
|
551
|
+
installed?: string;
|
|
552
|
+
}>;
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Build a CloudSandboxBackend from explicit options or the environment:
|
|
556
|
+
* PHONE_USE_SANDBOX_URL + PHONE_USE_SANDBOX_TOKEN (printed by
|
|
557
|
+
* `phone-use sandbox env <id>`).
|
|
558
|
+
*/
|
|
559
|
+
declare function createCloudSandboxBackend(config?: Partial<CloudSandboxBackendOptions>): CloudSandboxBackend;
|
|
560
|
+
//#endregion
|
|
480
561
|
//#region src/backends/device-runner.d.ts
|
|
481
562
|
/**
|
|
482
563
|
* A device-runner is addressed purely by URL, so it takes no DeviceConfig
|
|
@@ -535,6 +616,8 @@ declare class DeviceRunnerBackend extends BaseDeviceBackend {
|
|
|
535
616
|
device?: string;
|
|
536
617
|
}>;
|
|
537
618
|
}
|
|
619
|
+
/** Backend for a phone-runner reached by URL (defaults come from
|
|
620
|
+
* `PHONE_USE_RUNNER_URL` / `PHONE_USE_RUNNER_TOKEN` when `config` is omitted). */
|
|
538
621
|
declare const createDeviceRunnerBackend: (config?: DeviceRunnerConfig) => DeviceRunnerBackend;
|
|
539
622
|
//#endregion
|
|
540
623
|
//#region src/lifecycle.d.ts
|
|
@@ -743,7 +826,7 @@ declare const ios: {
|
|
|
743
826
|
* deliberately not re-exported here.
|
|
744
827
|
*/
|
|
745
828
|
/** The published package version (kept in sync with package.json by the release flow). */
|
|
746
|
-
declare const VERSION = "0.
|
|
829
|
+
declare const VERSION = "0.3.1";
|
|
747
830
|
//#endregion
|
|
748
|
-
export { ALL_CAPABILITIES, AbortedError, type ActOptions, type Action, type ActionEvidence, ActionFailedError, type ActionResult, type ActionVerb, type AlertAction, type AlertOutcome, type AndroidDeviceConfig, type BackendAlertResult, type BackendFactory, BaseDeviceBackend, type Capability, type CommonDeviceConfig, type CompiledSkill, type CreateDeviceHandleOptions, type Device, type DeviceBackend, type DeviceConfig, DeviceCore, DeviceInUseError, DeviceNotFoundError, type DevicePlatform, DeviceRunnerBackend, type DeviceStatus, type ElementQuery, type IosConnectOptions, type IosDeviceConfig, type IosLaunchOptions, type Observation, type ObserveResult, type ObservedElement, type OpenAppResult, PhoneUseError, type PhoneUseErrorCode, type PhoneUseErrorDetails, type PressTarget, type Rect, type RenderState, type Resolution, type ResolveOpts, type ScrollDirection, SecretStore, SessionNotFoundError, type Snapshot, type SnapshotNode, TimeoutError, type UiElement, UnsupportedCapabilityError, VERSION, buildObserveResult, createAgentDeviceBackend, createDeviceHandle, createDeviceRunnerBackend, describeError, executeAction, getBackendFactory, ios, labelMatches, listBackends, matchInElements, registerBackend, toActions, toPhoneUseError };
|
|
831
|
+
export { ALL_CAPABILITIES, AbortedError, type ActOptions, type Action, type ActionEvidence, ActionFailedError, type ActionResult, type ActionVerb, type AlertAction, type AlertOutcome, type AndroidDeviceConfig, type BackendAlertResult, type BackendFactory, BaseDeviceBackend, type Capability, CloudSandboxBackend, type CloudSandboxBackendOptions, type CommonDeviceConfig, type CompiledSkill, type CreateDeviceHandleOptions, type Device, type DeviceBackend, type DeviceConfig, DeviceCore, DeviceInUseError, DeviceNotFoundError, type DevicePlatform, DeviceRunnerBackend, type DeviceRunnerConfig, type DeviceStatus, type ElementQuery, type IosConnectOptions, type IosDeviceConfig, type IosLaunchOptions, type Observation, type ObserveResult, type ObservedElement, type OpenAppResult, PhoneUseError, type PhoneUseErrorCode, type PhoneUseErrorDetails, type PressTarget, type Rect, type RenderState, type Resolution, type ResolveOpts, type SandboxRpcFailure, type SandboxRpcMethod, type SandboxRpcRequest, type SandboxRpcResponse, type SandboxRpcSuccess, type ScrollDirection, SecretStore, SessionNotFoundError, type Snapshot, type SnapshotNode, TimeoutError, type UiElement, UnsupportedCapabilityError, VERSION, buildObserveResult, createAgentDeviceBackend, createCloudSandboxBackend, createDeviceHandle, createDeviceRunnerBackend, describeError, executeAction, getBackendFactory, ios, labelMatches, listBackends, matchInElements, registerBackend, toActions, toPhoneUseError };
|
|
749
832
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { a as registerBackend, c as DeviceInUseError, d as SessionNotFoundError, f as TimeoutError, i as listBackends, l as DeviceNotFoundError, m as toPhoneUseError, n as BaseDeviceBackend, o as AbortedError, p as UnsupportedCapabilityError, r as getBackendFactory, s as ActionFailedError, t as ALL_CAPABILITIES, u as PhoneUseError } from "./device-Xsy_LPUF.mjs";
|
|
2
2
|
import { createAgentDeviceClient } from "agent-device";
|
|
3
|
+
import { writeFile } from "node:fs/promises";
|
|
3
4
|
import { execFile } from "node:child_process";
|
|
4
5
|
import { promisify } from "node:util";
|
|
5
6
|
//#region src/observe.ts
|
|
@@ -1453,6 +1454,138 @@ function createAgentDeviceBackend(config) {
|
|
|
1453
1454
|
return new AgentDeviceBackend(config);
|
|
1454
1455
|
}
|
|
1455
1456
|
//#endregion
|
|
1457
|
+
//#region src/backends/cloud-sandbox.ts
|
|
1458
|
+
var CloudSandboxBackend = class extends BaseDeviceBackend {
|
|
1459
|
+
endpoint;
|
|
1460
|
+
token;
|
|
1461
|
+
fetchImpl;
|
|
1462
|
+
constructor(opts) {
|
|
1463
|
+
super("phone-use-cloud", opts.capabilities ?? ALL_CAPABILITIES);
|
|
1464
|
+
this.endpoint = opts.endpoint.replace(/\/+$/, "");
|
|
1465
|
+
this.token = opts.token;
|
|
1466
|
+
this.fetchImpl = opts.fetch ?? globalThis.fetch;
|
|
1467
|
+
}
|
|
1468
|
+
async rpc(method, ...args) {
|
|
1469
|
+
const response = await this.fetchImpl(`${this.endpoint}/rpc`, {
|
|
1470
|
+
method: "POST",
|
|
1471
|
+
headers: {
|
|
1472
|
+
authorization: `Bearer ${this.token}`,
|
|
1473
|
+
"content-type": "application/json"
|
|
1474
|
+
},
|
|
1475
|
+
body: JSON.stringify({
|
|
1476
|
+
method,
|
|
1477
|
+
args
|
|
1478
|
+
})
|
|
1479
|
+
});
|
|
1480
|
+
const body = await response.json().catch(() => ({}));
|
|
1481
|
+
if (!response.ok || !("ok" in body)) throw new PhoneUseError(("error" in body && typeof body.error === "string" ? body.error : void 0) ?? ("message" in body ? body.message : void 0) ?? `HTTP ${response.status}`, {
|
|
1482
|
+
code: "UNKNOWN",
|
|
1483
|
+
retryable: false
|
|
1484
|
+
});
|
|
1485
|
+
if (!body.ok) throw new PhoneUseError(body.error.message, {
|
|
1486
|
+
code: normalizeErrorCode(body.error.code),
|
|
1487
|
+
retryable: body.error.retryable ?? false
|
|
1488
|
+
});
|
|
1489
|
+
return body.result;
|
|
1490
|
+
}
|
|
1491
|
+
snapshot(opts) {
|
|
1492
|
+
return this.rpc("snapshot", opts);
|
|
1493
|
+
}
|
|
1494
|
+
async screenshot(opts) {
|
|
1495
|
+
const result = await this.rpc("screenshot", { overlayRefs: opts.overlayRefs });
|
|
1496
|
+
await writeFile(opts.path, Buffer.from(result.base64, "base64"));
|
|
1497
|
+
return { path: opts.path };
|
|
1498
|
+
}
|
|
1499
|
+
press(target) {
|
|
1500
|
+
return this.rpc("press", target);
|
|
1501
|
+
}
|
|
1502
|
+
longPress(ref, durationMs) {
|
|
1503
|
+
return this.rpc("longPress", ref, durationMs);
|
|
1504
|
+
}
|
|
1505
|
+
fill(ref, text) {
|
|
1506
|
+
return this.rpc("fill", ref, text);
|
|
1507
|
+
}
|
|
1508
|
+
typeText(text) {
|
|
1509
|
+
return this.rpc("typeText", text);
|
|
1510
|
+
}
|
|
1511
|
+
pressKey(key) {
|
|
1512
|
+
return this.rpc("pressKey", key);
|
|
1513
|
+
}
|
|
1514
|
+
scroll(direction) {
|
|
1515
|
+
return this.rpc("scroll", direction);
|
|
1516
|
+
}
|
|
1517
|
+
pan(x, y, dx, dy, durationMs) {
|
|
1518
|
+
return this.rpc("pan", x, y, dx, dy, durationMs);
|
|
1519
|
+
}
|
|
1520
|
+
waitForText(text, timeoutMs) {
|
|
1521
|
+
return this.rpc("waitForText", text, timeoutMs);
|
|
1522
|
+
}
|
|
1523
|
+
systemAlert(action) {
|
|
1524
|
+
return this.rpc("systemAlert", action);
|
|
1525
|
+
}
|
|
1526
|
+
home() {
|
|
1527
|
+
return this.rpc("home");
|
|
1528
|
+
}
|
|
1529
|
+
back() {
|
|
1530
|
+
return this.rpc("back");
|
|
1531
|
+
}
|
|
1532
|
+
openApp(opts) {
|
|
1533
|
+
return this.rpc("openApp", opts);
|
|
1534
|
+
}
|
|
1535
|
+
listApps() {
|
|
1536
|
+
return this.rpc("listApps");
|
|
1537
|
+
}
|
|
1538
|
+
closeSession() {
|
|
1539
|
+
return this.rpc("closeSession");
|
|
1540
|
+
}
|
|
1541
|
+
/** Upload a zipped .app bundle (base64) and install it on the sandbox device. */
|
|
1542
|
+
installApp(base64Zip) {
|
|
1543
|
+
return this.rpc("installApp", base64Zip);
|
|
1544
|
+
}
|
|
1545
|
+
};
|
|
1546
|
+
/**
|
|
1547
|
+
* Build a CloudSandboxBackend from explicit options or the environment:
|
|
1548
|
+
* PHONE_USE_SANDBOX_URL + PHONE_USE_SANDBOX_TOKEN (printed by
|
|
1549
|
+
* `phone-use sandbox env <id>`).
|
|
1550
|
+
*/
|
|
1551
|
+
function createCloudSandboxBackend(config) {
|
|
1552
|
+
const endpoint = config?.endpoint ?? process.env.PHONE_USE_SANDBOX_URL;
|
|
1553
|
+
const token = config?.token ?? process.env.PHONE_USE_SANDBOX_TOKEN;
|
|
1554
|
+
if (!endpoint || !token) throw new PhoneUseError("cloud sandbox backend needs PHONE_USE_SANDBOX_URL and PHONE_USE_SANDBOX_TOKEN (see `phone-use sandbox env <id>`)", {
|
|
1555
|
+
code: "BACKEND_NOT_FOUND",
|
|
1556
|
+
retryable: false
|
|
1557
|
+
});
|
|
1558
|
+
return new CloudSandboxBackend({
|
|
1559
|
+
...config,
|
|
1560
|
+
endpoint,
|
|
1561
|
+
token
|
|
1562
|
+
});
|
|
1563
|
+
}
|
|
1564
|
+
function normalizeErrorCode(code) {
|
|
1565
|
+
if ((/* @__PURE__ */ new Set([
|
|
1566
|
+
"DEVICE_NOT_FOUND",
|
|
1567
|
+
"DEVICE_IN_USE",
|
|
1568
|
+
"SESSION_NOT_FOUND",
|
|
1569
|
+
"TIMEOUT",
|
|
1570
|
+
"ACTION_FAILED",
|
|
1571
|
+
"UNSUPPORTED_CAPABILITY",
|
|
1572
|
+
"BACKEND_NOT_FOUND",
|
|
1573
|
+
"ABORTED",
|
|
1574
|
+
"UNKNOWN"
|
|
1575
|
+
])).has(code ?? "")) return code;
|
|
1576
|
+
return {
|
|
1577
|
+
device_gone: "DEVICE_NOT_FOUND",
|
|
1578
|
+
sandbox_not_found: "DEVICE_NOT_FOUND",
|
|
1579
|
+
timeout: "TIMEOUT",
|
|
1580
|
+
session_conflict: "DEVICE_IN_USE",
|
|
1581
|
+
target_not_found: "ACTION_FAILED",
|
|
1582
|
+
unauthorized: "ABORTED",
|
|
1583
|
+
payload_too_large: "ACTION_FAILED",
|
|
1584
|
+
bad_request: "ACTION_FAILED",
|
|
1585
|
+
internal: "UNKNOWN"
|
|
1586
|
+
}[code ?? ""] ?? "UNKNOWN";
|
|
1587
|
+
}
|
|
1588
|
+
//#endregion
|
|
1456
1589
|
//#region src/backends/device-runner.ts
|
|
1457
1590
|
const RUNNER_CAPABILITIES = [
|
|
1458
1591
|
"snapshot",
|
|
@@ -1605,6 +1738,8 @@ var DeviceRunnerBackend = class extends BaseDeviceBackend {
|
|
|
1605
1738
|
return this.#rpc("get_context");
|
|
1606
1739
|
}
|
|
1607
1740
|
};
|
|
1741
|
+
/** Backend for a phone-runner reached by URL (defaults come from
|
|
1742
|
+
* `PHONE_USE_RUNNER_URL` / `PHONE_USE_RUNNER_TOKEN` when `config` is omitted). */
|
|
1608
1743
|
const createDeviceRunnerBackend = (config) => new DeviceRunnerBackend(config);
|
|
1609
1744
|
//#endregion
|
|
1610
1745
|
//#region src/exec.ts
|
|
@@ -1994,9 +2129,9 @@ const ios = {
|
|
|
1994
2129
|
* deliberately not re-exported here.
|
|
1995
2130
|
*/
|
|
1996
2131
|
/** The published package version (kept in sync with package.json by the release flow). */
|
|
1997
|
-
const VERSION = "0.
|
|
2132
|
+
const VERSION = "0.3.1";
|
|
1998
2133
|
registerBackend("agent-device", createAgentDeviceBackend);
|
|
1999
2134
|
//#endregion
|
|
2000
|
-
export { ALL_CAPABILITIES, AbortedError, ActionFailedError, BaseDeviceBackend, DeviceCore, DeviceInUseError, DeviceNotFoundError, DeviceRunnerBackend, PhoneUseError, SecretStore, SessionNotFoundError, TimeoutError, UnsupportedCapabilityError, VERSION, buildObserveResult, createAgentDeviceBackend, createDeviceHandle, createDeviceRunnerBackend, describeError, executeAction, getBackendFactory, ios, labelMatches, listBackends, matchInElements, registerBackend, toActions, toPhoneUseError };
|
|
2135
|
+
export { ALL_CAPABILITIES, AbortedError, ActionFailedError, BaseDeviceBackend, CloudSandboxBackend, DeviceCore, DeviceInUseError, DeviceNotFoundError, DeviceRunnerBackend, PhoneUseError, SecretStore, SessionNotFoundError, TimeoutError, UnsupportedCapabilityError, VERSION, buildObserveResult, createAgentDeviceBackend, createCloudSandboxBackend, createDeviceHandle, createDeviceRunnerBackend, describeError, executeAction, getBackendFactory, ios, labelMatches, listBackends, matchInElements, registerBackend, toActions, toPhoneUseError };
|
|
2001
2136
|
|
|
2002
2137
|
//# sourceMappingURL=index.mjs.map
|