@autenai/sdk 0.4.0 → 0.6.0
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 +760 -0
- package/bin/auten.js +2 -0
- package/dist/cli/add-phone.d.ts +2 -0
- package/dist/cli/add-phone.d.ts.map +1 -0
- package/dist/cli/add-phone.js +254 -0
- package/dist/cli/add-phone.js.map +1 -0
- package/dist/cli/autocomplete.d.ts +31 -0
- package/dist/cli/autocomplete.d.ts.map +1 -0
- package/dist/cli/autocomplete.js +438 -0
- package/dist/cli/autocomplete.js.map +1 -0
- package/dist/cli/build-apk.d.ts +2 -0
- package/dist/cli/build-apk.d.ts.map +1 -0
- package/dist/cli/build-apk.js +97 -0
- package/dist/cli/build-apk.js.map +1 -0
- package/dist/cli/creds.d.ts +2 -0
- package/dist/cli/creds.d.ts.map +1 -0
- package/dist/cli/creds.js +161 -0
- package/dist/cli/creds.js.map +1 -0
- package/dist/cli/devices.d.ts +2 -0
- package/dist/cli/devices.d.ts.map +1 -0
- package/dist/cli/devices.js +38 -0
- package/dist/cli/devices.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +111 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/keys.d.ts +2 -0
- package/dist/cli/keys.d.ts.map +1 -0
- package/dist/cli/keys.js +88 -0
- package/dist/cli/keys.js.map +1 -0
- package/dist/cli/login.d.ts +2 -0
- package/dist/cli/login.d.ts.map +1 -0
- package/dist/cli/login.js +35 -0
- package/dist/cli/login.js.map +1 -0
- package/dist/cli/logo.d.ts +2 -0
- package/dist/cli/logo.d.ts.map +1 -0
- package/dist/cli/logo.js +11 -0
- package/dist/cli/logo.js.map +1 -0
- package/dist/cli/me.d.ts +2 -0
- package/dist/cli/me.d.ts.map +1 -0
- package/dist/cli/me.js +19 -0
- package/dist/cli/me.js.map +1 -0
- package/dist/cli/shell.d.ts +2 -0
- package/dist/cli/shell.d.ts.map +1 -0
- package/dist/cli/shell.js +22 -0
- package/dist/cli/shell.js.map +1 -0
- package/dist/cli/task.d.ts +2 -0
- package/dist/cli/task.d.ts.map +1 -0
- package/dist/cli/task.js +148 -0
- package/dist/cli/task.js.map +1 -0
- package/dist/cli/tasks.d.ts +2 -0
- package/dist/cli/tasks.d.ts.map +1 -0
- package/dist/cli/tasks.js +76 -0
- package/dist/cli/tasks.js.map +1 -0
- package/dist/cli/util.d.ts +46 -0
- package/dist/cli/util.d.ts.map +1 -0
- package/dist/cli/util.js +134 -0
- package/dist/cli/util.js.map +1 -0
- package/dist/package.json +56 -0
- package/dist/src/client.d.ts +92 -0
- package/dist/src/client.d.ts.map +1 -0
- package/dist/src/client.js +131 -0
- package/dist/src/client.js.map +1 -0
- package/dist/src/errors.d.ts +16 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +31 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/index.d.ts +7 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +5 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/phone.d.ts +124 -0
- package/dist/src/phone.d.ts.map +1 -0
- package/dist/src/phone.js +129 -0
- package/dist/src/phone.js.map +1 -0
- package/dist/src/transport.d.ts +14 -0
- package/dist/src/transport.d.ts.map +1 -0
- package/dist/src/transport.js +71 -0
- package/dist/src/transport.js.map +1 -0
- package/dist/src/types.d.ts +142 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/package.json +43 -26
- package/dist/index.d.mts +0 -500
- package/dist/index.d.ts +0 -500
- package/dist/index.js +0 -450
- package/dist/index.mjs +0 -418
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { Transport, DEFAULT_BASE_URL } from "./transport.js";
|
|
2
|
+
import { Phone } from "./phone.js";
|
|
3
|
+
/**
|
|
4
|
+
* Auten — top-level SDK client. Wraps the relay's REST API with typed
|
|
5
|
+
* methods grouped by resource:
|
|
6
|
+
*
|
|
7
|
+
* const auten = new Auten({ apiKey: process.env.AUTEN_API_KEY });
|
|
8
|
+
* const me = await auten.me();
|
|
9
|
+
* const devices = await auten.devices.list();
|
|
10
|
+
* const { task_id } = await auten.tasks.create({ device: devices[0].serial, prompt: "open chrome" });
|
|
11
|
+
* const result = await auten.tasks.wait(task_id);
|
|
12
|
+
* const phone = auten.phone(devices[0].serial);
|
|
13
|
+
* await phone.tap(500, 800);
|
|
14
|
+
*/
|
|
15
|
+
export class Auten {
|
|
16
|
+
t;
|
|
17
|
+
constructor(config) {
|
|
18
|
+
this.t = new Transport(config.apiKey, config.baseUrl ?? DEFAULT_BASE_URL, config.timeoutMs);
|
|
19
|
+
}
|
|
20
|
+
get baseUrl() { return this.t.baseUrl; }
|
|
21
|
+
/** Identity + counters for the calling key. */
|
|
22
|
+
me() {
|
|
23
|
+
return this.t.get("/v1/me");
|
|
24
|
+
}
|
|
25
|
+
// ── Devices ──────────────────────────────────────────────────────
|
|
26
|
+
devices = {
|
|
27
|
+
list: async () => {
|
|
28
|
+
const r = await this.t.get("/v1/devices");
|
|
29
|
+
return r.devices;
|
|
30
|
+
},
|
|
31
|
+
get: async (serial) => {
|
|
32
|
+
const all = await this.devices.list();
|
|
33
|
+
return all.find((d) => d.serial === serial) ?? null;
|
|
34
|
+
},
|
|
35
|
+
/** First device that's currently online, or null. */
|
|
36
|
+
firstOnline: async () => {
|
|
37
|
+
const all = await this.devices.list();
|
|
38
|
+
return all.find((d) => d.online) ?? null;
|
|
39
|
+
},
|
|
40
|
+
stats: (serial) => this.t.get(`/v1/devices/${encodeURIComponent(serial)}/stats`),
|
|
41
|
+
};
|
|
42
|
+
// ── Tasks ────────────────────────────────────────────────────────
|
|
43
|
+
tasks = {
|
|
44
|
+
create: (input) => {
|
|
45
|
+
return this.t.post("/v1/tasks", {
|
|
46
|
+
device_serial: input.device,
|
|
47
|
+
prompt: input.prompt,
|
|
48
|
+
mode: input.mode,
|
|
49
|
+
speed: input.speed,
|
|
50
|
+
webhook_url: input.webhook_url,
|
|
51
|
+
webhook_secret: input.webhook_secret,
|
|
52
|
+
timeout_seconds: input.timeout_seconds,
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
get: (id) => this.t.get(`/v1/tasks/${encodeURIComponent(id)}`),
|
|
56
|
+
list: async (opts = {}) => {
|
|
57
|
+
const q = new URLSearchParams();
|
|
58
|
+
if (opts.device)
|
|
59
|
+
q.set("device", opts.device);
|
|
60
|
+
if (opts.status)
|
|
61
|
+
q.set("status", opts.status);
|
|
62
|
+
if (opts.limit !== undefined)
|
|
63
|
+
q.set("limit", String(opts.limit));
|
|
64
|
+
const qs = q.toString();
|
|
65
|
+
const r = await this.t.get(`/v1/tasks${qs ? `?${qs}` : ""}`);
|
|
66
|
+
return r.tasks;
|
|
67
|
+
},
|
|
68
|
+
cancel: (id) => this.t.post(`/v1/tasks/${encodeURIComponent(id)}/cancel`),
|
|
69
|
+
/**
|
|
70
|
+
* Poll until the task reaches a terminal state. Backs off from `intervalMs`
|
|
71
|
+
* (default 1s) and aborts at `timeoutMs` (default 5 min).
|
|
72
|
+
* Returns the final Task object.
|
|
73
|
+
*/
|
|
74
|
+
wait: async (id, opts = {}) => {
|
|
75
|
+
const interval = opts.intervalMs ?? 1000;
|
|
76
|
+
const deadline = Date.now() + (opts.timeoutMs ?? 300_000);
|
|
77
|
+
// First fetch is immediate so the caller doesn't pay an interval delay
|
|
78
|
+
// for a task that's already done by the time wait() is called.
|
|
79
|
+
let t = await this.tasks.get(id);
|
|
80
|
+
while (t.status === "queued" || t.status === "running") {
|
|
81
|
+
if (Date.now() > deadline) {
|
|
82
|
+
throw new Error(`task ${id} did not complete within ${opts.timeoutMs ?? 300_000}ms`);
|
|
83
|
+
}
|
|
84
|
+
await new Promise((r) => setTimeout(r, interval));
|
|
85
|
+
t = await this.tasks.get(id);
|
|
86
|
+
}
|
|
87
|
+
return t;
|
|
88
|
+
},
|
|
89
|
+
/**
|
|
90
|
+
* One-shot helper: create + wait. Returns the final Task.
|
|
91
|
+
*
|
|
92
|
+
* const result = await auten.tasks.run({ device, prompt: "999÷3", speed: "lightning" });
|
|
93
|
+
* console.log(result.verified, result.result?.summary);
|
|
94
|
+
*/
|
|
95
|
+
run: async (input, waitOpts) => {
|
|
96
|
+
const created = await this.tasks.create(input);
|
|
97
|
+
return this.tasks.wait(created.task_id, waitOpts);
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
// ── API keys ─────────────────────────────────────────────────────
|
|
101
|
+
keys = {
|
|
102
|
+
list: async () => {
|
|
103
|
+
const r = await this.t.get("/v1/keys");
|
|
104
|
+
return r.keys;
|
|
105
|
+
},
|
|
106
|
+
/** Returns the new key with the FULL secret in `key`. Store it — the
|
|
107
|
+
* listing endpoint never reveals it again. */
|
|
108
|
+
create: (input = {}) => this.t.post("/v1/keys", input),
|
|
109
|
+
revoke: (id) => this.t.del(`/v1/keys/${encodeURIComponent(id)}`),
|
|
110
|
+
};
|
|
111
|
+
// ── Credentials (cross-device) ───────────────────────────────────
|
|
112
|
+
// Per-device save / reveal lives on `auten.phone(serial).credentials`;
|
|
113
|
+
// these are the helpers for "I want to see / delete one credential
|
|
114
|
+
// and I have its UUID, not its (serial, service) pair".
|
|
115
|
+
credentials = {
|
|
116
|
+
/** Every credential the calling key can see, across all of the owner's
|
|
117
|
+
* devices. Each row carries `id` and `deviceSerial`. */
|
|
118
|
+
list: async () => {
|
|
119
|
+
const r = await this.t.get("/v1/credentials");
|
|
120
|
+
return r.credentials;
|
|
121
|
+
},
|
|
122
|
+
/** Delete a credential by its UUID. The relay verifies the calling key
|
|
123
|
+
* owns the device the credential belongs to. */
|
|
124
|
+
deleteById: (id) => this.t.del(`/v1/credentials/${encodeURIComponent(id)}`),
|
|
125
|
+
};
|
|
126
|
+
/** Phone handle for direct control / per-device credentials. */
|
|
127
|
+
phone(serial) {
|
|
128
|
+
return new Phone(this.t, serial);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare class AutenError extends Error {
|
|
2
|
+
readonly cause?: unknown | undefined;
|
|
3
|
+
constructor(message: string, cause?: unknown | undefined);
|
|
4
|
+
}
|
|
5
|
+
export declare class AuthError extends AutenError {
|
|
6
|
+
constructor(message?: string);
|
|
7
|
+
}
|
|
8
|
+
export declare class ApiError extends AutenError {
|
|
9
|
+
readonly status: number;
|
|
10
|
+
constructor(message: string, status: number);
|
|
11
|
+
}
|
|
12
|
+
export declare class DeviceOfflineError extends AutenError {
|
|
13
|
+
readonly serial: string;
|
|
14
|
+
constructor(serial: string);
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,UAAW,SAAQ,KAAK;aACU,KAAK,CAAC,EAAE,OAAO;gBAAhD,OAAO,EAAE,MAAM,EAAkB,KAAK,CAAC,EAAE,OAAO,YAAA;CAI7D;AAED,qBAAa,SAAU,SAAQ,UAAU;gBAC3B,OAAO,SAAiB;CAIrC;AAED,qBAAa,QAAS,SAAQ,UAAU;aACO,MAAM,EAAE,MAAM;gBAA/C,OAAO,EAAE,MAAM,EAAkB,MAAM,EAAE,MAAM;CAI5D;AAED,qBAAa,kBAAmB,SAAQ,UAAU;aACpB,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM;CAI3C"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export class AutenError extends Error {
|
|
2
|
+
cause;
|
|
3
|
+
constructor(message, cause) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.cause = cause;
|
|
6
|
+
this.name = "AutenError";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export class AuthError extends AutenError {
|
|
10
|
+
constructor(message = "unauthorized") {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = "AuthError";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export class ApiError extends AutenError {
|
|
16
|
+
status;
|
|
17
|
+
constructor(message, status) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.status = status;
|
|
20
|
+
this.name = "ApiError";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export class DeviceOfflineError extends AutenError {
|
|
24
|
+
serial;
|
|
25
|
+
constructor(serial) {
|
|
26
|
+
super(`device ${serial} is not connected`);
|
|
27
|
+
this.serial = serial;
|
|
28
|
+
this.name = "DeviceOfflineError";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,UAAW,SAAQ,KAAK;IACU;IAA7C,YAAY,OAAe,EAAkB,KAAe;QAC1D,KAAK,CAAC,OAAO,CAAC,CAAC;QAD4B,UAAK,GAAL,KAAK,CAAU;QAE1D,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,OAAO,SAAU,SAAQ,UAAU;IACvC,YAAY,OAAO,GAAG,cAAc;QAClC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAED,MAAM,OAAO,QAAS,SAAQ,UAAU;IACO;IAA7C,YAAY,OAAe,EAAkB,MAAc;QACzD,KAAK,CAAC,OAAO,CAAC,CAAC;QAD4B,WAAM,GAAN,MAAM,CAAQ;QAEzD,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,UAAU;IACpB;IAA5B,YAA4B,MAAc;QACxC,KAAK,CAAC,UAAU,MAAM,mBAAmB,CAAC,CAAC;QADjB,WAAM,GAAN,MAAM,CAAQ;QAExC,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { Auten } from "./client.js";
|
|
2
|
+
export { Phone } from "./phone.js";
|
|
3
|
+
export { Transport, DEFAULT_BASE_URL } from "./transport.js";
|
|
4
|
+
export { AutenError, AuthError, ApiError, DeviceOfflineError, } from "./errors.js";
|
|
5
|
+
export type { AutenConfig, } from "./client.js";
|
|
6
|
+
export type { Speed, TaskMode, TaskStatus, Device, Task, TaskTurn, TaskArtifact, CreateTaskInput, CreateTaskResponse, ListTasksOptions, Whoami, ApiKey, ApiKeyWithSecret, CreateKeyInput, Credential, SaveCredentialInput, SomElement, LookResult, KeyName, } from "./types.js";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EACL,UAAU,EACV,SAAS,EACT,QAAQ,EACR,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,KAAK,EACL,QAAQ,EACR,UAAU,EACV,MAAM,EACN,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,MAAM,EACN,MAAM,EACN,gBAAgB,EAChB,cAAc,EACd,UAAU,EACV,mBAAmB,EACnB,UAAU,EACV,UAAU,EACV,OAAO,GACR,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EACL,UAAU,EACV,SAAS,EACT,QAAQ,EACR,kBAAkB,GACnB,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { Transport } from "./transport.js";
|
|
2
|
+
import type { LookResult, KeyName, Credential, SaveCredentialInput, CreateTaskResponse, Speed, TaskMode } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Phone — wraps a single device. All control calls go through the relay's
|
|
5
|
+
* owner-scoped phone-proxy endpoint, which forwards them via the WS reverse
|
|
6
|
+
* tunnel to the APK on the device.
|
|
7
|
+
*
|
|
8
|
+
* const phone = auten.phone("a4e0eff201d020fd");
|
|
9
|
+
* const screen = await phone.look();
|
|
10
|
+
* await phone.tap(500, 800);
|
|
11
|
+
* await phone.task("open Instagram and like 5 posts");
|
|
12
|
+
*/
|
|
13
|
+
export declare class Phone {
|
|
14
|
+
private readonly t;
|
|
15
|
+
readonly serial: string;
|
|
16
|
+
constructor(t: Transport, serial: string);
|
|
17
|
+
private get base();
|
|
18
|
+
/**
|
|
19
|
+
* Forward an HTTP envelope to the phone APK through the relay tunnel.
|
|
20
|
+
* Most callers should use the named methods below; this is the escape
|
|
21
|
+
* hatch for endpoints we haven't wrapped (and for forward-compat with
|
|
22
|
+
* APK changes that ship before SDK updates).
|
|
23
|
+
*/
|
|
24
|
+
proxy<T = unknown>(method: "GET" | "POST", path: string, body?: unknown, timeoutMs?: number): Promise<T>;
|
|
25
|
+
look(): Promise<LookResult>;
|
|
26
|
+
screenshot(): Promise<{
|
|
27
|
+
jpeg: string;
|
|
28
|
+
width: number;
|
|
29
|
+
height: number;
|
|
30
|
+
durationMs: number;
|
|
31
|
+
}>;
|
|
32
|
+
tap(x: number, y: number): Promise<{
|
|
33
|
+
ok: boolean;
|
|
34
|
+
}>;
|
|
35
|
+
longPress(x: number, y: number, durationMs?: number): Promise<{
|
|
36
|
+
ok: boolean;
|
|
37
|
+
}>;
|
|
38
|
+
swipe(x1: number, y1: number, x2: number, y2: number, durationMs?: number): Promise<{
|
|
39
|
+
ok: boolean;
|
|
40
|
+
}>;
|
|
41
|
+
/**
|
|
42
|
+
* Type text into the focused field. Pass `target: { x, y }` of an
|
|
43
|
+
* editable element to bypass the soft keyboard (uses accessibility
|
|
44
|
+
* ACTION_SET_TEXT — instant, no layout shift).
|
|
45
|
+
*/
|
|
46
|
+
type(text: string, target?: {
|
|
47
|
+
x: number;
|
|
48
|
+
y: number;
|
|
49
|
+
}): Promise<{
|
|
50
|
+
ok: boolean;
|
|
51
|
+
}>;
|
|
52
|
+
key(name: KeyName): Promise<{
|
|
53
|
+
ok: boolean;
|
|
54
|
+
}>;
|
|
55
|
+
/** Force-stops the package first (clean slate), then launches it. */
|
|
56
|
+
launch(packageName: string): Promise<{
|
|
57
|
+
ok: boolean;
|
|
58
|
+
}>;
|
|
59
|
+
stop(packageName: string): Promise<{
|
|
60
|
+
ok: boolean;
|
|
61
|
+
}>;
|
|
62
|
+
/** ACTION_VIEW intent — one-shot navigation. Pass `pkg` to pin a browser. */
|
|
63
|
+
openUrl(url: string, pkg?: string): Promise<{
|
|
64
|
+
ok: boolean;
|
|
65
|
+
url: string;
|
|
66
|
+
package?: string;
|
|
67
|
+
}>;
|
|
68
|
+
status(): Promise<unknown>;
|
|
69
|
+
info(): Promise<unknown>;
|
|
70
|
+
/** Kill all third-party apps + press home. Useful before benchmarks. */
|
|
71
|
+
reset(): Promise<{
|
|
72
|
+
ok: boolean;
|
|
73
|
+
killedCount: number;
|
|
74
|
+
}>;
|
|
75
|
+
notifications(): Promise<unknown[]>;
|
|
76
|
+
clearNotifications(): Promise<{
|
|
77
|
+
ok: boolean;
|
|
78
|
+
}>;
|
|
79
|
+
clipboardSet(text: string): Promise<{
|
|
80
|
+
ok: boolean;
|
|
81
|
+
}>;
|
|
82
|
+
clipboardGet(): Promise<{
|
|
83
|
+
ok: boolean;
|
|
84
|
+
text: string;
|
|
85
|
+
}>;
|
|
86
|
+
pasteClipboard(target?: {
|
|
87
|
+
x: number;
|
|
88
|
+
y: number;
|
|
89
|
+
}): Promise<{
|
|
90
|
+
ok: boolean;
|
|
91
|
+
}>;
|
|
92
|
+
/**
|
|
93
|
+
* Shortcut for `auten.tasks.create({ device: this.serial, prompt, ... })`.
|
|
94
|
+
* Returns the task handle; await `auten.tasks.wait(id)` for the result.
|
|
95
|
+
*/
|
|
96
|
+
task(prompt: string, opts?: {
|
|
97
|
+
speed?: Speed;
|
|
98
|
+
mode?: TaskMode;
|
|
99
|
+
timeout_seconds?: number;
|
|
100
|
+
webhook_url?: string;
|
|
101
|
+
webhook_secret?: string;
|
|
102
|
+
}): Promise<CreateTaskResponse>;
|
|
103
|
+
readonly credentials: {
|
|
104
|
+
save: (input: SaveCredentialInput) => Promise<{
|
|
105
|
+
ok: boolean;
|
|
106
|
+
service: string;
|
|
107
|
+
}>;
|
|
108
|
+
/** List this device's credentials. Each row carries `id` (UUID),
|
|
109
|
+
* pass to `deleteById()` if you don't have the service name handy. */
|
|
110
|
+
list: () => Promise<Credential[]>;
|
|
111
|
+
reveal: <T = Record<string, unknown>>(service: string) => Promise<T>;
|
|
112
|
+
/** Delete by service name (unique per device). */
|
|
113
|
+
delete: (service: string) => Promise<{
|
|
114
|
+
ok: boolean;
|
|
115
|
+
}>;
|
|
116
|
+
/** Delete by UUID. Routed through the cross-device endpoint; the
|
|
117
|
+
* relay verifies the credential belongs to a device this key owns. */
|
|
118
|
+
deleteById: (id: string) => Promise<{
|
|
119
|
+
ok: boolean;
|
|
120
|
+
id: string;
|
|
121
|
+
}>;
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=phone.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phone.d.ts","sourceRoot":"","sources":["../../src/phone.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phone — wraps a single device. All control calls go through the relay's
|
|
3
|
+
* owner-scoped phone-proxy endpoint, which forwards them via the WS reverse
|
|
4
|
+
* tunnel to the APK on the device.
|
|
5
|
+
*
|
|
6
|
+
* const phone = auten.phone("a4e0eff201d020fd");
|
|
7
|
+
* const screen = await phone.look();
|
|
8
|
+
* await phone.tap(500, 800);
|
|
9
|
+
* await phone.task("open Instagram and like 5 posts");
|
|
10
|
+
*/
|
|
11
|
+
export class Phone {
|
|
12
|
+
t;
|
|
13
|
+
serial;
|
|
14
|
+
constructor(t, serial) {
|
|
15
|
+
this.t = t;
|
|
16
|
+
this.serial = serial;
|
|
17
|
+
}
|
|
18
|
+
get base() {
|
|
19
|
+
return `/v1/devices/${encodeURIComponent(this.serial)}`;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Forward an HTTP envelope to the phone APK through the relay tunnel.
|
|
23
|
+
* Most callers should use the named methods below; this is the escape
|
|
24
|
+
* hatch for endpoints we haven't wrapped (and for forward-compat with
|
|
25
|
+
* APK changes that ship before SDK updates).
|
|
26
|
+
*/
|
|
27
|
+
proxy(method, path, body, timeoutMs) {
|
|
28
|
+
return this.t.post(`${this.base}/proxy`, { method, path, body, timeout_ms: timeoutMs });
|
|
29
|
+
}
|
|
30
|
+
// ── Vision ────────────────────────────────────────────────────────
|
|
31
|
+
look() {
|
|
32
|
+
return this.proxy("POST", "/look");
|
|
33
|
+
}
|
|
34
|
+
screenshot() {
|
|
35
|
+
return this.proxy("POST", "/screenshot");
|
|
36
|
+
}
|
|
37
|
+
// ── Input ─────────────────────────────────────────────────────────
|
|
38
|
+
tap(x, y) {
|
|
39
|
+
return this.proxy("POST", "/tap", { x: Math.round(x), y: Math.round(y) });
|
|
40
|
+
}
|
|
41
|
+
longPress(x, y, durationMs = 1000) {
|
|
42
|
+
return this.proxy("POST", "/long_press", { x: Math.round(x), y: Math.round(y), duration: durationMs });
|
|
43
|
+
}
|
|
44
|
+
swipe(x1, y1, x2, y2, durationMs = 300) {
|
|
45
|
+
return this.proxy("POST", "/swipe", {
|
|
46
|
+
x1: Math.round(x1), y1: Math.round(y1),
|
|
47
|
+
x2: Math.round(x2), y2: Math.round(y2),
|
|
48
|
+
duration: durationMs,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Type text into the focused field. Pass `target: { x, y }` of an
|
|
53
|
+
* editable element to bypass the soft keyboard (uses accessibility
|
|
54
|
+
* ACTION_SET_TEXT — instant, no layout shift).
|
|
55
|
+
*/
|
|
56
|
+
type(text, target) {
|
|
57
|
+
return this.proxy("POST", "/type", target
|
|
58
|
+
? { text, x: Math.round(target.x), y: Math.round(target.y) }
|
|
59
|
+
: { text });
|
|
60
|
+
}
|
|
61
|
+
key(name) {
|
|
62
|
+
return this.proxy("POST", "/key", { key: name });
|
|
63
|
+
}
|
|
64
|
+
// ── Apps ──────────────────────────────────────────────────────────
|
|
65
|
+
/** Force-stops the package first (clean slate), then launches it. */
|
|
66
|
+
async launch(packageName) {
|
|
67
|
+
await this.proxy("POST", "/stop", { package: packageName }).catch(() => { });
|
|
68
|
+
return this.proxy("POST", "/launch", { package: packageName });
|
|
69
|
+
}
|
|
70
|
+
stop(packageName) {
|
|
71
|
+
return this.proxy("POST", "/stop", { package: packageName });
|
|
72
|
+
}
|
|
73
|
+
/** ACTION_VIEW intent — one-shot navigation. Pass `pkg` to pin a browser. */
|
|
74
|
+
openUrl(url, pkg) {
|
|
75
|
+
return this.proxy("POST", "/open_url", pkg ? { url, package: pkg } : { url });
|
|
76
|
+
}
|
|
77
|
+
// ── Status / events ──────────────────────────────────────────────
|
|
78
|
+
status() { return this.proxy("GET", "/status"); }
|
|
79
|
+
info() { return this.proxy("GET", "/info"); }
|
|
80
|
+
/** Kill all third-party apps + press home. Useful before benchmarks. */
|
|
81
|
+
reset() { return this.proxy("POST", "/reset"); }
|
|
82
|
+
notifications() { return this.proxy("GET", "/notifications"); }
|
|
83
|
+
clearNotifications() { return this.proxy("POST", "/notifications/clear"); }
|
|
84
|
+
// ── Clipboard ────────────────────────────────────────────────────
|
|
85
|
+
clipboardSet(text) {
|
|
86
|
+
return this.proxy("POST", "/clipboard/set", { text });
|
|
87
|
+
}
|
|
88
|
+
clipboardGet() {
|
|
89
|
+
return this.proxy("GET", "/clipboard/get");
|
|
90
|
+
}
|
|
91
|
+
pasteClipboard(target) {
|
|
92
|
+
return this.proxy("POST", "/paste-clipboard", target
|
|
93
|
+
? { x: Math.round(target.x), y: Math.round(target.y) }
|
|
94
|
+
: {});
|
|
95
|
+
}
|
|
96
|
+
// ── Task dispatch (sugar) ─────────────────────────────────────────
|
|
97
|
+
/**
|
|
98
|
+
* Shortcut for `auten.tasks.create({ device: this.serial, prompt, ... })`.
|
|
99
|
+
* Returns the task handle; await `auten.tasks.wait(id)` for the result.
|
|
100
|
+
*/
|
|
101
|
+
task(prompt, opts) {
|
|
102
|
+
return this.t.post("/v1/tasks", {
|
|
103
|
+
device_serial: this.serial,
|
|
104
|
+
prompt,
|
|
105
|
+
mode: opts?.mode,
|
|
106
|
+
speed: opts?.speed,
|
|
107
|
+
timeout_seconds: opts?.timeout_seconds,
|
|
108
|
+
webhook_url: opts?.webhook_url,
|
|
109
|
+
webhook_secret: opts?.webhook_secret,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
// ── Credentials (encrypted server-side, scoped to this device) ───
|
|
113
|
+
credentials = {
|
|
114
|
+
save: (input) => this.t.post(`${this.base}/credentials`, input),
|
|
115
|
+
/** List this device's credentials. Each row carries `id` (UUID),
|
|
116
|
+
* pass to `deleteById()` if you don't have the service name handy. */
|
|
117
|
+
list: async () => {
|
|
118
|
+
const r = await this.t.get(`${this.base}/credentials`);
|
|
119
|
+
return r.credentials;
|
|
120
|
+
},
|
|
121
|
+
reveal: (service) => this.t.get(`${this.base}/credentials/${encodeURIComponent(service)}/reveal`),
|
|
122
|
+
/** Delete by service name (unique per device). */
|
|
123
|
+
delete: (service) => this.t.del(`${this.base}/credentials/${encodeURIComponent(service)}`),
|
|
124
|
+
/** Delete by UUID. Routed through the cross-device endpoint; the
|
|
125
|
+
* relay verifies the credential belongs to a device this key owns. */
|
|
126
|
+
deleteById: (id) => this.t.del(`/v1/credentials/${encodeURIComponent(id)}`),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=phone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phone.js","sourceRoot":"","sources":["../../src/phone.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const DEFAULT_BASE_URL = "https://relay.auten.ai";
|
|
2
|
+
export declare class Transport {
|
|
3
|
+
readonly baseUrl: string;
|
|
4
|
+
readonly apiKey: string;
|
|
5
|
+
readonly timeoutMs: number;
|
|
6
|
+
constructor(apiKey: string, baseUrl?: string, timeoutMs?: number);
|
|
7
|
+
private headers;
|
|
8
|
+
get<T>(path: string, timeoutMs?: number): Promise<T>;
|
|
9
|
+
post<T>(path: string, body?: unknown, timeoutMs?: number): Promise<T>;
|
|
10
|
+
put<T>(path: string, body?: unknown, timeoutMs?: number): Promise<T>;
|
|
11
|
+
del<T>(path: string, timeoutMs?: number): Promise<T>;
|
|
12
|
+
private request;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/transport.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,gBAAgB,2BAA2B,CAAC;AAGzD,qBAAa,SAAS;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,MAAyB,EAAE,SAAS,GAAE,MAA2B;IAOtG,OAAO,CAAC,OAAO;IAOT,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAIpD,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAIrE,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAIpE,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;YAI5C,OAAO;CAiCtB"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { AuthError, ApiError, DeviceOfflineError } from "./errors.js";
|
|
2
|
+
export const DEFAULT_BASE_URL = "https://relay.auten.ai";
|
|
3
|
+
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
4
|
+
export class Transport {
|
|
5
|
+
baseUrl;
|
|
6
|
+
apiKey;
|
|
7
|
+
timeoutMs;
|
|
8
|
+
constructor(apiKey, baseUrl = DEFAULT_BASE_URL, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
9
|
+
if (!apiKey)
|
|
10
|
+
throw new AuthError("apiKey required");
|
|
11
|
+
this.apiKey = apiKey;
|
|
12
|
+
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
13
|
+
this.timeoutMs = timeoutMs;
|
|
14
|
+
}
|
|
15
|
+
headers() {
|
|
16
|
+
return {
|
|
17
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
18
|
+
"Content-Type": "application/json",
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
async get(path, timeoutMs) {
|
|
22
|
+
return this.request("GET", path, undefined, timeoutMs);
|
|
23
|
+
}
|
|
24
|
+
async post(path, body, timeoutMs) {
|
|
25
|
+
return this.request("POST", path, body, timeoutMs);
|
|
26
|
+
}
|
|
27
|
+
async put(path, body, timeoutMs) {
|
|
28
|
+
return this.request("PUT", path, body, timeoutMs);
|
|
29
|
+
}
|
|
30
|
+
async del(path, timeoutMs) {
|
|
31
|
+
return this.request("DELETE", path, undefined, timeoutMs);
|
|
32
|
+
}
|
|
33
|
+
async request(method, path, body, timeoutMs) {
|
|
34
|
+
const url = `${this.baseUrl}${path}`;
|
|
35
|
+
let res;
|
|
36
|
+
try {
|
|
37
|
+
res = await fetch(url, {
|
|
38
|
+
method,
|
|
39
|
+
headers: this.headers(),
|
|
40
|
+
body: body == null ? undefined : JSON.stringify(body),
|
|
41
|
+
signal: AbortSignal.timeout(timeoutMs ?? this.timeoutMs),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
throw new ApiError(`network error calling ${method} ${path}: ${err instanceof Error ? err.message : String(err)}`, 0);
|
|
46
|
+
}
|
|
47
|
+
const text = await res.text();
|
|
48
|
+
if (res.status === 401)
|
|
49
|
+
throw new AuthError(text || "unauthorized");
|
|
50
|
+
if (res.status === 403)
|
|
51
|
+
throw new AuthError(text || "forbidden");
|
|
52
|
+
if (res.status === 503 && /not connected/i.test(text)) {
|
|
53
|
+
const m = text.match(/serial\W*([\w-]+)/);
|
|
54
|
+
throw new DeviceOfflineError(m?.[1] ?? "<unknown>");
|
|
55
|
+
}
|
|
56
|
+
if (!res.ok) {
|
|
57
|
+
throw new ApiError(`${method} ${path}: ${res.status} ${text.slice(0, 200)}`, res.status);
|
|
58
|
+
}
|
|
59
|
+
if (!text)
|
|
60
|
+
return undefined;
|
|
61
|
+
try {
|
|
62
|
+
return JSON.parse(text);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// Some endpoints (e.g. /apk/latest) stream non-JSON. The SDK doesn't
|
|
66
|
+
// call those; if we land here it's a contract violation worth surfacing.
|
|
67
|
+
throw new ApiError(`${method} ${path}: response was not JSON`, res.status);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/transport.ts"],"names":[],"mappings":"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"}
|