@phone-use/sdk 0.1.0 → 0.1.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/{backend-Cbr2tIN-.d.mts → backend-CkJkkw5Z.d.mts} +6 -6
- package/dist/{device-BzPnHvQy.mjs → device-Xsy_LPUF.mjs} +2 -2
- package/dist/device-Xsy_LPUF.mjs.map +1 -0
- package/dist/index.d.mts +12 -12
- package/dist/index.mjs +7 -7
- package/dist/index.mjs.map +1 -1
- package/dist/testing.d.mts +6 -6
- package/dist/testing.mjs +5 -5
- package/dist/testing.mjs.map +1 -1
- package/package.json +15 -1
- package/src/actions.ts +6 -6
- package/src/backend.ts +4 -5
- package/src/backends/agent-device.ts +2 -3
- package/src/backends/ios.ts +4 -4
- package/src/config.ts +4 -5
- package/src/device.ts +3 -3
- package/src/errors.ts +3 -3
- package/src/exec.ts +1 -1
- package/src/index.ts +3 -3
- package/src/lifecycle.ts +5 -5
- package/src/observe.ts +1 -1
- package/src/secrets.ts +2 -2
- package/src/testing.ts +4 -4
- package/dist/device-BzPnHvQy.mjs.map +0 -1
|
@@ -9,7 +9,7 @@ type Rect = {
|
|
|
9
9
|
/**
|
|
10
10
|
* One accessibility-tree node as reported by a backend snapshot. The SDK's own
|
|
11
11
|
* vocabulary — structurally compatible with agent-device's nodes but never
|
|
12
|
-
* importing its types (
|
|
12
|
+
* importing its types (no backend type in the public API).
|
|
13
13
|
*/
|
|
14
14
|
type SnapshotNode = {
|
|
15
15
|
ref?: string | undefined;
|
|
@@ -79,7 +79,7 @@ type PhoneUseErrorDetails = Record<string, unknown> & {
|
|
|
79
79
|
backendCode?: string | undefined;
|
|
80
80
|
};
|
|
81
81
|
/**
|
|
82
|
-
* Root of the typed error tree
|
|
82
|
+
* Root of the typed error tree.
|
|
83
83
|
* Every backend method rejects only with PhoneUseError subclasses; agent-device
|
|
84
84
|
* (or any transport) errors are normalized at the boundary by
|
|
85
85
|
* {@link toPhoneUseError} so no backend type ever reaches the public API. Each
|
|
@@ -196,14 +196,14 @@ type AndroidDeviceConfig = CommonDeviceConfig & {
|
|
|
196
196
|
};
|
|
197
197
|
/**
|
|
198
198
|
* Device configuration: a discriminated union on `platform`, never a
|
|
199
|
-
* stringly-typed capability blob (
|
|
200
|
-
*
|
|
199
|
+
* stringly-typed capability blob (learning from Appium's leaks).
|
|
200
|
+
* Plain types — no zod in the SDK public API.
|
|
201
201
|
*/
|
|
202
202
|
type DeviceConfig = IosDeviceConfig | AndroidDeviceConfig;
|
|
203
203
|
//#endregion
|
|
204
204
|
//#region src/backend.d.ts
|
|
205
205
|
/**
|
|
206
|
-
* The backend contract
|
|
206
|
+
* The backend contract: a STRUCTURAL interface —
|
|
207
207
|
* any object with these methods is a backend — plus an optional
|
|
208
208
|
* {@link BaseDeviceBackend} class with the plumbing done (Appium BaseDriver
|
|
209
209
|
* ergonomics). Methods reject only with PhoneUseError subclasses; backends
|
|
@@ -313,4 +313,4 @@ declare function getBackendFactory(name: string): BackendFactory;
|
|
|
313
313
|
declare function listBackends(): string[];
|
|
314
314
|
//#endregion
|
|
315
315
|
export { Snapshot as A, AlertAction as C, PressTarget as D, OpenAppResult as E, Rect as O, ALL_CAPABILITIES as S, Capability as T, PhoneUseErrorDetails as _, listBackends as a, UnsupportedCapabilityError as b, CommonDeviceConfig as c, AbortedError as d, ActionFailedError as f, PhoneUseErrorCode as g, PhoneUseError as h, getBackendFactory as i, SnapshotNode as j, ScrollDirection as k, DeviceConfig as l, DeviceNotFoundError as m, BaseDeviceBackend as n, registerBackend as o, DeviceInUseError as p, DeviceBackend as r, AndroidDeviceConfig as s, BackendFactory as t, IosDeviceConfig as u, SessionNotFoundError as v, BackendAlertResult as w, toPhoneUseError as x, TimeoutError as y };
|
|
316
|
-
//# sourceMappingURL=backend-
|
|
316
|
+
//# sourceMappingURL=backend-CkJkkw5Z.d.mts.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isAgentDeviceError } from "agent-device";
|
|
2
2
|
//#region src/errors.ts
|
|
3
3
|
/**
|
|
4
|
-
* Root of the typed error tree
|
|
4
|
+
* Root of the typed error tree.
|
|
5
5
|
* Every backend method rejects only with PhoneUseError subclasses; agent-device
|
|
6
6
|
* (or any transport) errors are normalized at the boundary by
|
|
7
7
|
* {@link toPhoneUseError} so no backend type ever reaches the public API. Each
|
|
@@ -281,4 +281,4 @@ const ALL_CAPABILITIES = [
|
|
|
281
281
|
//#endregion
|
|
282
282
|
export { registerBackend as a, DeviceInUseError as c, SessionNotFoundError as d, TimeoutError as f, listBackends as i, DeviceNotFoundError as l, toPhoneUseError as m, BaseDeviceBackend as n, AbortedError as o, UnsupportedCapabilityError as p, getBackendFactory as r, ActionFailedError as s, ALL_CAPABILITIES as t, PhoneUseError as u };
|
|
283
283
|
|
|
284
|
-
//# sourceMappingURL=device-
|
|
284
|
+
//# sourceMappingURL=device-Xsy_LPUF.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-Xsy_LPUF.mjs","names":[],"sources":["../src/errors.ts","../src/backend.ts","../src/device.ts"],"sourcesContent":["import { isAgentDeviceError } from 'agent-device';\n\n/**\n * Stable machine-readable error codes carried by every {@link PhoneUseError}.\n *\n * Codes are deliberately string-identical to agent-device's where a concept\n * maps 1:1 (DEVICE_NOT_FOUND, SESSION_NOT_FOUND, ...) so existing harness\n * checks like `(e as {code?: string}).code === 'SESSION_NOT_FOUND'` keep\n * working unchanged across the normalization boundary.\n */\nexport type PhoneUseErrorCode =\n | 'DEVICE_NOT_FOUND'\n | 'DEVICE_IN_USE'\n | 'SESSION_NOT_FOUND'\n | 'TIMEOUT'\n | 'ACTION_FAILED'\n | 'UNSUPPORTED_CAPABILITY'\n | 'BACKEND_NOT_FOUND'\n | 'ABORTED'\n | 'UNKNOWN';\n\n/** Structured, code-specific context attached to a {@link PhoneUseError}. */\nexport type PhoneUseErrorDetails = Record<string, unknown> & {\n /** Preserved from agent-device details.hint — describeError renders it. */\n hint?: string | undefined;\n /** The raw backend code when we collapse to ACTION_FAILED. */\n backendCode?: string | undefined;\n};\n\n/**\n * Root of the typed error tree.\n * Every backend method rejects only with PhoneUseError subclasses; agent-device\n * (or any transport) errors are normalized at the boundary by\n * {@link toPhoneUseError} so no backend type ever reaches the public API. Each\n * error carries a stable `code` and an explicit `retryable` flag — the field\n * agent loops need to decide retry-vs-replan.\n */\nexport class PhoneUseError extends Error {\n /** Stable machine-readable code — the field to branch on. */\n readonly code: PhoneUseErrorCode;\n /** Whether retrying the same call can plausibly succeed. */\n readonly retryable: boolean;\n /** Optional structured context (hint, raw backend code, ...). */\n readonly details?: PhoneUseErrorDetails | undefined;\n\n constructor(\n message: string,\n opts: {\n code: PhoneUseErrorCode;\n retryable: boolean;\n details?: PhoneUseErrorDetails | undefined;\n cause?: unknown;\n },\n ) {\n super(message, opts.cause === undefined ? undefined : { cause: opts.cause });\n this.name = new.target.name;\n this.code = opts.code;\n this.retryable = opts.retryable;\n this.details = opts.details;\n }\n}\n\n/** No device matched the selection (`DEVICE_NOT_FOUND`, not retryable). */\nexport class DeviceNotFoundError extends PhoneUseError {\n constructor(message: string, opts: { details?: PhoneUseErrorDetails | undefined; cause?: unknown } = {}) {\n super(message, { code: 'DEVICE_NOT_FOUND', retryable: false, ...opts });\n }\n}\n\n/** The device is held by another session (`DEVICE_IN_USE`, retryable). */\nexport class DeviceInUseError extends PhoneUseError {\n constructor(message: string, opts: { details?: PhoneUseErrorDetails | undefined; cause?: unknown } = {}) {\n super(message, { code: 'DEVICE_IN_USE', retryable: true, ...opts });\n }\n}\n\n/** No live session — the device/session was closed (`SESSION_NOT_FOUND`, not retryable). */\nexport class SessionNotFoundError extends PhoneUseError {\n constructor(message: string, opts: { details?: PhoneUseErrorDetails | undefined; cause?: unknown } = {}) {\n super(message, { code: 'SESSION_NOT_FOUND', retryable: false, ...opts });\n }\n}\n\n/** A deadline elapsed before the operation completed (`TIMEOUT`, retryable). */\nexport class TimeoutError extends PhoneUseError {\n constructor(message: string, opts: { details?: PhoneUseErrorDetails | undefined; cause?: unknown } = {}) {\n super(message, { code: 'TIMEOUT', retryable: true, ...opts });\n }\n}\n\n/** A device action failed to execute (`ACTION_FAILED`, retryable). */\nexport class ActionFailedError extends PhoneUseError {\n constructor(message: string, opts: { details?: PhoneUseErrorDetails | undefined; cause?: unknown } = {}) {\n super(message, { code: 'ACTION_FAILED', retryable: true, ...opts });\n }\n}\n\n/** The backend does not implement the capability (`UNSUPPORTED_CAPABILITY`, not retryable). */\nexport class UnsupportedCapabilityError extends PhoneUseError {\n /** The backend that rejected the call. */\n readonly backend: string;\n /** The missing capability. */\n readonly capability: string;\n\n constructor(opts: { backend: string; capability: string; cause?: unknown }) {\n super(`backend \"${opts.backend}\" does not support \"${opts.capability}\"`, {\n code: 'UNSUPPORTED_CAPABILITY',\n retryable: false,\n details: { backend: opts.backend, capability: opts.capability },\n ...(opts.cause === undefined ? {} : { cause: opts.cause }),\n });\n this.backend = opts.backend;\n this.capability = opts.capability;\n }\n}\n\n/**\n * The caller's AbortSignal fired (`ABORTED`, not retryable). Abort is caller\n * control flow, not a device outcome — never retried.\n */\nexport class AbortedError extends PhoneUseError {\n constructor(message = 'aborted by caller', opts: { cause?: unknown } = {}) {\n super(message, { code: 'ABORTED', retryable: false, ...opts });\n }\n}\n\nconst TIMEOUT_RE = /\\btime[d ]?\\s?out\\b|\\btimeout\\b/i;\n\n/**\n * Boundary normalizer: ANY thrown value → PhoneUseError. agent-device AppError\n * codes map per the table below; an existing PhoneUseError passes through\n * untouched; unknown values wrap as UNKNOWN (not retryable). The original\n * error always rides on `cause`; details (including hint) are preserved.\n */\nexport function toPhoneUseError(\n err: unknown,\n ctx: { backend?: string; capability?: string } = {},\n): PhoneUseError {\n if (err instanceof PhoneUseError) return err;\n\n if (isAgentDeviceError(err)) {\n const e = err as Error & { code?: string; details?: Record<string, unknown> };\n const message = e.message || String(e.code ?? 'agent-device error');\n const details: PhoneUseErrorDetails = { ...(e.details ?? {}) };\n const opts = { details, cause: err };\n // Timeout is a shape, not a code, in agent-device — heuristic on message,\n // verified against real agent-device errors on macOS.\n if (TIMEOUT_RE.test(message)) return new TimeoutError(message, opts);\n switch (e.code) {\n case 'DEVICE_NOT_FOUND':\n return new DeviceNotFoundError(message, opts);\n case 'DEVICE_IN_USE':\n return new DeviceInUseError(message, opts);\n case 'SESSION_NOT_FOUND':\n return new SessionNotFoundError(message, opts);\n case 'UNSUPPORTED_PLATFORM':\n case 'UNSUPPORTED_OPERATION':\n case 'NOT_IMPLEMENTED':\n return new UnsupportedCapabilityError({\n backend: ctx.backend ?? 'unknown',\n capability: ctx.capability ?? String(e.code),\n cause: err,\n });\n default:\n return new ActionFailedError(message, {\n details: { ...details, backendCode: e.code === undefined ? undefined : String(e.code) },\n cause: err,\n });\n }\n }\n\n if (err instanceof Error) {\n if (TIMEOUT_RE.test(err.message)) return new TimeoutError(err.message, { cause: err });\n return new PhoneUseError(err.message, { code: 'UNKNOWN', retryable: false, cause: err });\n }\n return new PhoneUseError(String(err), { code: 'UNKNOWN', retryable: false, cause: err });\n}\n","import type { DeviceConfig } from './config.ts';\nimport type {\n AlertAction,\n BackendAlertResult,\n Capability,\n OpenAppResult,\n PressTarget,\n ScrollDirection,\n Snapshot,\n} from './device.ts';\nimport { PhoneUseError, UnsupportedCapabilityError } from './errors.ts';\n\n/**\n * The backend contract: a STRUCTURAL interface —\n * any object with these methods is a backend — plus an optional\n * {@link BaseDeviceBackend} class with the plumbing done (Appium BaseDriver\n * ergonomics). Methods reject only with PhoneUseError subclasses; backends\n * normalize their transport's errors at the boundary.\n */\nexport interface DeviceBackend {\n /** Stable backend identifier, e.g. `\"agent-device\"`. */\n readonly backendName: string;\n /** The capabilities this backend actually implements. */\n readonly capabilities: ReadonlySet<Capability>;\n\n /** Capture the accessibility tree of the frontmost app. */\n snapshot(opts?: { interactiveOnly?: boolean | undefined; depth?: number | undefined }): Promise<Snapshot>;\n /** Save a screenshot to `path` (optionally with `@ref` overlays drawn). */\n screenshot(opts: { path: string; overlayRefs?: boolean | undefined }): Promise<{ path: string }>;\n /** Tap an element ref or raw coordinates. */\n press(target: PressTarget): Promise<void>;\n /** Long-press an element ref. */\n longPress(ref: string, durationMs?: number): Promise<void>;\n /** Focus an element and replace its text. */\n fill(ref: string, text: string): Promise<void>;\n /** Type into whatever currently has keyboard focus. */\n typeText(text: string): Promise<void>;\n /** Press a hardware/keyboard key (Return only, this cycle). */\n pressKey(key: 'return'): Promise<void>;\n /** Scroll the active scroll view one step. */\n scroll(direction: ScrollDirection): Promise<void>;\n /** Coordinate drag: touch down at (x,y), move by (dx,dy). Operates picker wheels, sliders, carousels. */\n pan(x: number, y: number, dx: number, dy: number, durationMs?: number): Promise<void>;\n /** Block until `text` appears on screen or the timeout elapses. */\n waitForText(text: string, timeoutMs?: number): Promise<void>;\n /** Read/accept/dismiss the app's own alert via the transport's alert command. */\n systemAlert(action: AlertAction): Promise<BackendAlertResult>;\n /** Go to the home screen. */\n home(): Promise<void>;\n /** Navigate back (hardware back / nav-bar back). */\n back(): Promise<void>;\n /** Open an app by name/bundle id, or a URL (deep link). */\n openApp(opts: {\n app?: string | undefined;\n url?: string | undefined;\n relaunch?: boolean | undefined;\n }): Promise<OpenAppResult>;\n /** List installed app bundle ids. */\n listApps(): Promise<string[]>;\n /** Close the transport session (idempotent; safe when none is open). */\n closeSession(): Promise<void>;\n}\n\n/**\n * Optional plumbing base: every method rejects with a typed\n * UnsupportedCapabilityError until overridden. Subclasses declare their\n * capability set and override exactly what they support.\n */\nexport abstract class BaseDeviceBackend implements DeviceBackend {\n readonly backendName: string;\n readonly capabilities: ReadonlySet<Capability>;\n\n protected constructor(backendName: string, capabilities: Iterable<Capability>) {\n this.backendName = backendName;\n this.capabilities = new Set(capabilities);\n }\n\n protected unsupported(capability: Capability): UnsupportedCapabilityError {\n return new UnsupportedCapabilityError({ backend: this.backendName, capability });\n }\n\n /** Throws UnsupportedCapabilityError unless this backend declares `capability`. */\n requireCapability(capability: Capability): void {\n if (!this.capabilities.has(capability)) throw this.unsupported(capability);\n }\n\n snapshot(_opts?: { interactiveOnly?: boolean | undefined; depth?: number | undefined }): Promise<Snapshot> {\n return Promise.reject(this.unsupported('snapshot'));\n }\n screenshot(_opts: { path: string; overlayRefs?: boolean | undefined }): Promise<{ path: string }> {\n return Promise.reject(this.unsupported('screenshot'));\n }\n press(_target: PressTarget): Promise<void> {\n return Promise.reject(this.unsupported('press'));\n }\n longPress(_ref: string, _durationMs?: number): Promise<void> {\n return Promise.reject(this.unsupported('longPress'));\n }\n fill(_ref: string, _text: string): Promise<void> {\n return Promise.reject(this.unsupported('fill'));\n }\n typeText(_text: string): Promise<void> {\n return Promise.reject(this.unsupported('type'));\n }\n pressKey(_key: 'return'): Promise<void> {\n return Promise.reject(this.unsupported('key'));\n }\n scroll(_direction: ScrollDirection): Promise<void> {\n return Promise.reject(this.unsupported('scroll'));\n }\n pan(_x: number, _y: number, _dx: number, _dy: number, _durationMs?: number): Promise<void> {\n return Promise.reject(this.unsupported('pan'));\n }\n waitForText(_text: string, _timeoutMs?: number): Promise<void> {\n return Promise.reject(this.unsupported('waitForText'));\n }\n systemAlert(_action: AlertAction): Promise<BackendAlertResult> {\n return Promise.reject(this.unsupported('alert'));\n }\n home(): Promise<void> {\n return Promise.reject(this.unsupported('home'));\n }\n back(): Promise<void> {\n return Promise.reject(this.unsupported('back'));\n }\n openApp(_opts: {\n app?: string | undefined;\n url?: string | undefined;\n relaunch?: boolean | undefined;\n }): Promise<OpenAppResult> {\n return Promise.reject(this.unsupported('openApp'));\n }\n listApps(): Promise<string[]> {\n return Promise.reject(this.unsupported('listApps'));\n }\n closeSession(): Promise<void> {\n return Promise.reject(this.unsupported('closeSession'));\n }\n}\n\n// ---------------------------------------------------------------------------\n// Runtime backend registry (registerBackend + the phone-backend-* naming\n// convention). A deliberate module-level Map: this IS the registry — mirrored\n// on permissions.ts's documented pattern.\n// ---------------------------------------------------------------------------\n\n/** Builds a backend from an optional {@link DeviceConfig}. */\nexport type BackendFactory = (config?: DeviceConfig) => DeviceBackend | Promise<DeviceBackend>;\n\nconst factories = new Map<string, BackendFactory>();\n\n/**\n * Register a backend factory under a unique name (the `phone-backend-*`\n * convention for third parties). Throws if the name is already taken.\n */\nexport function registerBackend(name: string, factory: BackendFactory): void {\n if (factories.has(name)) {\n throw new PhoneUseError(`backend \"${name}\" is already registered`, {\n code: 'ACTION_FAILED',\n retryable: false,\n });\n }\n factories.set(name, factory);\n}\n\n/** Look up a registered factory by name; throws `BACKEND_NOT_FOUND` if absent. */\nexport function getBackendFactory(name: string): BackendFactory {\n const factory = factories.get(name);\n if (!factory) {\n throw new PhoneUseError(\n `no backend named \"${name}\" — registered: ${[...factories.keys()].join(', ') || '(none)'}`,\n {\n code: 'BACKEND_NOT_FOUND',\n retryable: false,\n },\n );\n }\n return factory;\n}\n\n/** Names of every registered backend, in registration order. */\nexport function listBackends(): string[] {\n return [...factories.keys()];\n}\n","// ---------------------------------------------------------------------------\n// Shared device types — the SDK's own vocabulary, structurally compatible with\n// agent-device's snapshot nodes but never importing its types — no backend\n// type in the public API. Every optional is `| undefined` so\n// narrower backend types assign structurally under exactOptionalPropertyTypes.\n// ---------------------------------------------------------------------------\n\n/** Element geometry in screen points (same space as screenshot pixels at @1x). */\nexport type Rect = { x: number; y: number; width: number; height: number };\n\n/**\n * One accessibility-tree node as reported by a backend snapshot. The SDK's own\n * vocabulary — structurally compatible with agent-device's nodes but never\n * importing its types (no backend type in the public API).\n */\nexport type SnapshotNode = {\n ref?: string | undefined;\n type?: string | undefined;\n role?: string | undefined;\n label?: string | undefined;\n value?: string | undefined;\n identifier?: string | undefined;\n enabled?: boolean | undefined;\n selected?: boolean | undefined;\n focused?: boolean | undefined;\n interactionBlocked?: string | undefined;\n rect?: Rect | undefined;\n};\n\n/** One backend snapshot: the node list plus the frontmost app when known. */\nexport type Snapshot = {\n nodes: SnapshotNode[];\n appName?: string | undefined;\n appBundleId?: string | undefined;\n};\n\n/** Scroll gesture direction. */\nexport type ScrollDirection = 'up' | 'down' | 'left' | 'right';\n\n/** A press target: an element ref from a snapshot, or raw screen coordinates. */\nexport type PressTarget = { ref: string } | { x: number; y: number };\n\n/** What to do with a system alert: read it, accept it, or dismiss it. */\nexport type AlertAction = 'get' | 'accept' | 'dismiss';\n\n/** Raw result of a backend's system-alert command. */\nexport type BackendAlertResult = {\n alert?:\n | { title?: string | undefined; message?: string | undefined; buttons?: string[] | undefined }\n | null\n | undefined;\n handled?: boolean | undefined;\n button?: string | undefined;\n};\n\n/** What a backend reports after opening an app or URL. */\nexport type OpenAppResult = { appName?: string | undefined; appBundleId?: string | undefined };\n\n/** A backend feature a caller can query via `backend.capabilities`. */\nexport type Capability =\n | 'snapshot'\n | 'screenshot'\n | 'press'\n | 'longPress'\n | 'fill'\n | 'type'\n | 'key'\n | 'scroll'\n | 'pan'\n | 'waitForText'\n | 'alert'\n | 'home'\n | 'back'\n | 'openApp'\n | 'openUrl'\n | 'listApps'\n | 'closeSession';\n\n/** Every capability — what a full backend (agent-device iOS) declares. */\nexport const ALL_CAPABILITIES: readonly Capability[] = [\n 'snapshot',\n 'screenshot',\n 'press',\n 'longPress',\n 'fill',\n 'type',\n 'key',\n 'scroll',\n 'pan',\n 'waitForText',\n 'alert',\n 'home',\n 'back',\n 'openApp',\n 'openUrl',\n 'listApps',\n 'closeSession',\n];\n"],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as Snapshot, C as AlertAction, D as PressTarget, E as OpenAppResult, O as Rect, S as ALL_CAPABILITIES, T as Capability, _ as PhoneUseErrorDetails, a as listBackends, b as UnsupportedCapabilityError, c as CommonDeviceConfig, d as AbortedError, f as ActionFailedError, g as PhoneUseErrorCode, h as PhoneUseError, i as getBackendFactory, j as SnapshotNode, k as ScrollDirection, l as DeviceConfig, m as DeviceNotFoundError, n as BaseDeviceBackend, o as registerBackend, p as DeviceInUseError, r as DeviceBackend, s as AndroidDeviceConfig, t as BackendFactory, u as IosDeviceConfig, v as SessionNotFoundError, w as BackendAlertResult, x as toPhoneUseError, y as TimeoutError } from "./backend-
|
|
1
|
+
import { A as Snapshot, C as AlertAction, D as PressTarget, E as OpenAppResult, O as Rect, S as ALL_CAPABILITIES, T as Capability, _ as PhoneUseErrorDetails, a as listBackends, b as UnsupportedCapabilityError, c as CommonDeviceConfig, d as AbortedError, f as ActionFailedError, g as PhoneUseErrorCode, h as PhoneUseError, i as getBackendFactory, j as SnapshotNode, k as ScrollDirection, l as DeviceConfig, m as DeviceNotFoundError, n as BaseDeviceBackend, o as registerBackend, p as DeviceInUseError, r as DeviceBackend, s as AndroidDeviceConfig, t as BackendFactory, u as IosDeviceConfig, v as SessionNotFoundError, w as BackendAlertResult, x as toPhoneUseError, y as TimeoutError } from "./backend-CkJkkw5Z.mjs";
|
|
2
2
|
//#region src/observe.d.ts
|
|
3
3
|
/** One compressed observation: the frontmost app plus the rendered element list. */
|
|
4
4
|
type Observation = {
|
|
@@ -299,7 +299,7 @@ declare class DeviceCore {
|
|
|
299
299
|
//#endregion
|
|
300
300
|
//#region src/secrets.d.ts
|
|
301
301
|
/**
|
|
302
|
-
* `%variable%` secret substitution (
|
|
302
|
+
* `%variable%` secret substitution (Stagehand's pattern):
|
|
303
303
|
* the model/caller plans against NAMES; values are injected at the last moment
|
|
304
304
|
* before backend.fill/typeText and never rendered into Actions, results,
|
|
305
305
|
* observations, or traces. Redaction is best-effort belt-and-braces; the hard
|
|
@@ -343,13 +343,13 @@ type ElementQuery = {
|
|
|
343
343
|
/** Verbs a portable {@link Action} can carry. */
|
|
344
344
|
type ActionVerb = 'tap' | 'longPress' | 'fill' | 'type' | 'pressKey' | 'scroll' | 'openApp' | 'openUrl' | 'back' | 'home' | 'alert' | 'waitForText';
|
|
345
345
|
/**
|
|
346
|
-
* The observe→act seam
|
|
346
|
+
* The observe→act seam: a portable action
|
|
347
347
|
* descriptor carrying a re-resolvable {@link ElementQuery}. `observe()` returns
|
|
348
348
|
* these; `act()` re-resolves against the live tree and executes with no
|
|
349
349
|
* re-inference. A compiled skill is a stored `Action[]`.
|
|
350
350
|
*/
|
|
351
351
|
type Action = {
|
|
352
|
-
/** Versioned, documented UNSTABLE pre-1.0
|
|
352
|
+
/** Versioned, documented UNSTABLE pre-1.0. */
|
|
353
353
|
formatVersion: 0;
|
|
354
354
|
/** What to do. */
|
|
355
355
|
verb: ActionVerb;
|
|
@@ -381,7 +381,7 @@ type Action = {
|
|
|
381
381
|
screenTitle?: string | undefined;
|
|
382
382
|
} | undefined;
|
|
383
383
|
};
|
|
384
|
-
/** The stored-Action[] artifact (public TYPE, unstable FORMAT
|
|
384
|
+
/** The stored-Action[] artifact (public TYPE, unstable FORMAT pre-1.0). */
|
|
385
385
|
type CompiledSkill = {
|
|
386
386
|
formatVersion: 0;
|
|
387
387
|
name: string;
|
|
@@ -483,10 +483,10 @@ type DevicePlatform = 'ios' | 'android';
|
|
|
483
483
|
/** Lifecycle state of a {@link Device} handle. */
|
|
484
484
|
type DeviceStatus = 'running' | 'closed';
|
|
485
485
|
/**
|
|
486
|
-
* The Device lifecycle handle
|
|
487
|
-
*
|
|
488
|
-
*
|
|
489
|
-
*
|
|
486
|
+
* The Device lifecycle handle: id, pinned backend, close/dispose, idle lease +
|
|
487
|
+
* reaper — plus the action verb surface layered onto the same type.
|
|
488
|
+
* `ios.launch()` and `ios.connect()` return it; the future android engine will
|
|
489
|
+
* share `createDeviceHandle`.
|
|
490
490
|
*/
|
|
491
491
|
interface Device {
|
|
492
492
|
/** udid (iOS) / serial (Android). */
|
|
@@ -676,14 +676,14 @@ declare const ios: {
|
|
|
676
676
|
//#region src/index.d.ts
|
|
677
677
|
/**
|
|
678
678
|
* @phone-use/sdk — the device runtime SDK: engine-as-object lifecycle
|
|
679
|
-
* (ios.launch/connect → Device), Device backends, config, errors, capabilities
|
|
680
|
-
*
|
|
679
|
+
* (ios.launch/connect → Device), Device backends, config, errors, capabilities,
|
|
680
|
+
* and the action verb surface.
|
|
681
681
|
*
|
|
682
682
|
* The test double (FakeBackend) lives on the "@phone-use/sdk/testing" subpath,
|
|
683
683
|
* deliberately not re-exported here.
|
|
684
684
|
*/
|
|
685
685
|
/** The published package version (kept in sync with package.json by the release flow). */
|
|
686
|
-
declare const VERSION = "0.1.
|
|
686
|
+
declare const VERSION = "0.1.1";
|
|
687
687
|
//#endregion
|
|
688
688
|
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, 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, describeError, executeAction, getBackendFactory, ios, labelMatches, listBackends, matchInElements, registerBackend, toActions, toPhoneUseError };
|
|
689
689
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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-
|
|
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
3
|
import { execFile } from "node:child_process";
|
|
4
4
|
import { promisify } from "node:util";
|
|
@@ -854,7 +854,7 @@ var DeviceCore = class {
|
|
|
854
854
|
//#region src/secrets.ts
|
|
855
855
|
const MIN_SECRET_LENGTH = 4;
|
|
856
856
|
/**
|
|
857
|
-
* `%variable%` secret substitution (
|
|
857
|
+
* `%variable%` secret substitution (Stagehand's pattern):
|
|
858
858
|
* the model/caller plans against NAMES; values are injected at the last moment
|
|
859
859
|
* before backend.fill/typeText and never rendered into Actions, results,
|
|
860
860
|
* observations, or traces. Redaction is best-effort belt-and-braces; the hard
|
|
@@ -1009,8 +1009,8 @@ const POLL_STEPS_MS = [
|
|
|
1009
1009
|
800
|
|
1010
1010
|
];
|
|
1011
1011
|
/**
|
|
1012
|
-
* Resolve + auto-wait (
|
|
1013
|
-
* action, no caller sleep
|
|
1012
|
+
* Resolve + auto-wait (visible+hittable+enabled+settled on every
|
|
1013
|
+
* action, no caller sleep — and it must not double latency).
|
|
1014
1014
|
* Fast path: a fresh cache resolving to an actionable target executes with
|
|
1015
1015
|
* ZERO extra snapshots. Slow path: poll in place (never scroll — scrolling is
|
|
1016
1016
|
* the ladder's job, and polling must not dismiss transient menus) until the
|
|
@@ -1833,14 +1833,14 @@ const ios = {
|
|
|
1833
1833
|
//#region src/index.ts
|
|
1834
1834
|
/**
|
|
1835
1835
|
* @phone-use/sdk — the device runtime SDK: engine-as-object lifecycle
|
|
1836
|
-
* (ios.launch/connect → Device), Device backends, config, errors, capabilities
|
|
1837
|
-
*
|
|
1836
|
+
* (ios.launch/connect → Device), Device backends, config, errors, capabilities,
|
|
1837
|
+
* and the action verb surface.
|
|
1838
1838
|
*
|
|
1839
1839
|
* The test double (FakeBackend) lives on the "@phone-use/sdk/testing" subpath,
|
|
1840
1840
|
* deliberately not re-exported here.
|
|
1841
1841
|
*/
|
|
1842
1842
|
/** The published package version (kept in sync with package.json by the release flow). */
|
|
1843
|
-
const VERSION = "0.1.
|
|
1843
|
+
const VERSION = "0.1.1";
|
|
1844
1844
|
registerBackend("agent-device", createAgentDeviceBackend);
|
|
1845
1845
|
//#endregion
|
|
1846
1846
|
export { ALL_CAPABILITIES, AbortedError, ActionFailedError, BaseDeviceBackend, DeviceCore, DeviceInUseError, DeviceNotFoundError, PhoneUseError, SecretStore, SessionNotFoundError, TimeoutError, UnsupportedCapabilityError, VERSION, buildObserveResult, createAgentDeviceBackend, createDeviceHandle, describeError, executeAction, getBackendFactory, ios, labelMatches, listBackends, matchInElements, registerBackend, toActions, toPhoneUseError };
|