gpt-driver-node 1.0.0-alpha.1 → 1.0.0-alpha.2
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.cjs +154 -0
- package/dist/index.d.cts +37 -0
- package/dist/index.mjs +152 -0
- package/package.json +1 -2
- package/tsconfig.json +2 -1
- package/src/helpers.ts +0 -31
- package/src/index.ts +0 -151
- package/src/types.ts +0 -33
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var axios = require('axios');
|
|
4
|
+
var webdriverio = require('webdriverio');
|
|
5
|
+
var sharp = require('sharp');
|
|
6
|
+
|
|
7
|
+
const delay = async (milliseconds) => {
|
|
8
|
+
await new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
9
|
+
};
|
|
10
|
+
const getScreenshot = async (driver, deviceSize) => {
|
|
11
|
+
let screenshot = await driver.takeScreenshot();
|
|
12
|
+
if (driver.capabilities.platformName === "iOS") {
|
|
13
|
+
const imageBuffer = Buffer.from(screenshot, "base64");
|
|
14
|
+
const transformedImage = await sharp(imageBuffer).resize(deviceSize.width, deviceSize.height).toBuffer();
|
|
15
|
+
screenshot = transformedImage.toString("base64");
|
|
16
|
+
}
|
|
17
|
+
return screenshot;
|
|
18
|
+
};
|
|
19
|
+
const delayIfNeeded = async (lastResponseTime) => {
|
|
20
|
+
if (lastResponseTime == null) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const currentTime = Date.now();
|
|
24
|
+
const difference = currentTime - lastResponseTime;
|
|
25
|
+
if (difference < 1500) {
|
|
26
|
+
await delay(difference);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
class GptDriver {
|
|
31
|
+
apiKey;
|
|
32
|
+
baseUrl;
|
|
33
|
+
driver;
|
|
34
|
+
deviceConfig;
|
|
35
|
+
firestoreSessionId;
|
|
36
|
+
deviceSize;
|
|
37
|
+
lastCommandExecutionTime;
|
|
38
|
+
constructor(config) {
|
|
39
|
+
this.apiKey = config.apiKey;
|
|
40
|
+
this.baseUrl = "https://api.mobileboost.io";
|
|
41
|
+
if (config.driver !== void 0) {
|
|
42
|
+
this.driver = config.driver;
|
|
43
|
+
} else if (config.deviceConfig !== void 0) {
|
|
44
|
+
this.deviceConfig = config.deviceConfig;
|
|
45
|
+
} else {
|
|
46
|
+
throw new Error("Either provide an appium driver or a deviceConfig object");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async startSession() {
|
|
50
|
+
if (this.driver == void 0 && this.deviceConfig != void 0) {
|
|
51
|
+
const capabilities = {
|
|
52
|
+
platformName: this.deviceConfig.platform,
|
|
53
|
+
"appium:automationName": this.deviceConfig.platform === "Android" ? "UiAutomator2" : "XCUITest",
|
|
54
|
+
"appium:deviceName": this.deviceConfig.deviceName
|
|
55
|
+
};
|
|
56
|
+
const wdOpts = {
|
|
57
|
+
hostname: process.env.APPIUM_HOST || "localhost",
|
|
58
|
+
port: process.env.APPIUM_PORT != null ? parseInt(process.env.APPIUM_PORT, 10) : 4723,
|
|
59
|
+
logLevel: "info",
|
|
60
|
+
capabilities
|
|
61
|
+
};
|
|
62
|
+
this.driver = await webdriverio.remote(wdOpts);
|
|
63
|
+
}
|
|
64
|
+
const driver = this.driver;
|
|
65
|
+
const response = await axios.post(
|
|
66
|
+
`${this.baseUrl}/sessions/create`,
|
|
67
|
+
{
|
|
68
|
+
api_key: this.apiKey,
|
|
69
|
+
appium_session_id: driver.sessionId,
|
|
70
|
+
device_config: {
|
|
71
|
+
// @ts-ignore
|
|
72
|
+
platform: driver.capabilities.platformName,
|
|
73
|
+
// @ts-ignore
|
|
74
|
+
device: driver.capabilities.deviceName,
|
|
75
|
+
// @ts-ignore
|
|
76
|
+
os: driver.capabilities.platformVersion
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
const rect = await driver.getWindowRect();
|
|
81
|
+
this.deviceSize = { width: rect.width, height: rect.height };
|
|
82
|
+
this.firestoreSessionId = response.data.sessionId;
|
|
83
|
+
}
|
|
84
|
+
async stopSession({ status }) {
|
|
85
|
+
await axios.post(
|
|
86
|
+
`${this.baseUrl}/sessions/${this.firestoreSessionId}/stop`,
|
|
87
|
+
{
|
|
88
|
+
api_key: this.apiKey,
|
|
89
|
+
status
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
this.firestoreSessionId = void 0;
|
|
93
|
+
}
|
|
94
|
+
async execute(command, appiumHandler) {
|
|
95
|
+
const driver = this.driver;
|
|
96
|
+
if (appiumHandler != null) {
|
|
97
|
+
try {
|
|
98
|
+
await appiumHandler(driver);
|
|
99
|
+
} catch (e) {
|
|
100
|
+
await this.gptHandler(command);
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
await this.gptHandler(command);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async gptHandler(command) {
|
|
107
|
+
const driver = this.driver;
|
|
108
|
+
try {
|
|
109
|
+
let conditionSucceeded = false;
|
|
110
|
+
while (!conditionSucceeded) {
|
|
111
|
+
await delayIfNeeded(this.lastCommandExecutionTime);
|
|
112
|
+
const screenshot = await getScreenshot(driver, this.deviceSize);
|
|
113
|
+
const response = await axios.request(
|
|
114
|
+
{
|
|
115
|
+
url: `${this.baseUrl}/sessions/${this.firestoreSessionId}/execute`,
|
|
116
|
+
method: "POST",
|
|
117
|
+
data: {
|
|
118
|
+
api_key: this.apiKey,
|
|
119
|
+
command,
|
|
120
|
+
base64_screenshot: screenshot
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
const executeStatus = response.data.status;
|
|
125
|
+
if (executeStatus === "failed") {
|
|
126
|
+
throw new Error("Execution failed");
|
|
127
|
+
}
|
|
128
|
+
conditionSucceeded = executeStatus !== "inProgress";
|
|
129
|
+
const executeResponse = response.data;
|
|
130
|
+
for (const command2 of executeResponse.commands) {
|
|
131
|
+
await this.executeCommand(command2);
|
|
132
|
+
}
|
|
133
|
+
this.lastCommandExecutionTime = Date.now();
|
|
134
|
+
}
|
|
135
|
+
} catch (e) {
|
|
136
|
+
await this.stopSession({ status: "failed" });
|
|
137
|
+
throw e;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
async executeCommand(command) {
|
|
141
|
+
const firstAction = command.data.actions?.at(0);
|
|
142
|
+
if (firstAction?.type === "pause" && firstAction.duration != null) {
|
|
143
|
+
await delay(firstAction * 1e3);
|
|
144
|
+
} else {
|
|
145
|
+
await axios.request({
|
|
146
|
+
url: command.url,
|
|
147
|
+
method: command.method,
|
|
148
|
+
data: command.data
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
module.exports = GptDriver;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
interface AppiumHandler {
|
|
2
|
+
(driver: WebdriverIO.Browser): Promise<any>;
|
|
3
|
+
}
|
|
4
|
+
interface DeviceConfig {
|
|
5
|
+
platform: "iOS" | "Android";
|
|
6
|
+
deviceName?: string;
|
|
7
|
+
platformVersion?: string;
|
|
8
|
+
}
|
|
9
|
+
interface GptDriverConfig {
|
|
10
|
+
apiKey: string;
|
|
11
|
+
driver?: WebdriverIO.Browser;
|
|
12
|
+
deviceConfig?: DeviceConfig;
|
|
13
|
+
}
|
|
14
|
+
interface DeviceSize {
|
|
15
|
+
width: number;
|
|
16
|
+
height: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
declare class GptDriver {
|
|
20
|
+
apiKey: string;
|
|
21
|
+
baseUrl: string;
|
|
22
|
+
driver?: WebdriverIO.Browser;
|
|
23
|
+
deviceConfig?: DeviceConfig;
|
|
24
|
+
firestoreSessionId?: string;
|
|
25
|
+
deviceSize?: DeviceSize;
|
|
26
|
+
lastCommandExecutionTime?: number;
|
|
27
|
+
constructor(config: GptDriverConfig);
|
|
28
|
+
startSession(): Promise<void>;
|
|
29
|
+
stopSession({ status }: {
|
|
30
|
+
status: "failed" | "success";
|
|
31
|
+
}): Promise<void>;
|
|
32
|
+
execute(command: string, appiumHandler?: AppiumHandler): Promise<void>;
|
|
33
|
+
private gptHandler;
|
|
34
|
+
private executeCommand;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { GptDriver as default };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { remote } from 'webdriverio';
|
|
3
|
+
import sharp from 'sharp';
|
|
4
|
+
|
|
5
|
+
const delay = async (milliseconds) => {
|
|
6
|
+
await new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
7
|
+
};
|
|
8
|
+
const getScreenshot = async (driver, deviceSize) => {
|
|
9
|
+
let screenshot = await driver.takeScreenshot();
|
|
10
|
+
if (driver.capabilities.platformName === "iOS") {
|
|
11
|
+
const imageBuffer = Buffer.from(screenshot, "base64");
|
|
12
|
+
const transformedImage = await sharp(imageBuffer).resize(deviceSize.width, deviceSize.height).toBuffer();
|
|
13
|
+
screenshot = transformedImage.toString("base64");
|
|
14
|
+
}
|
|
15
|
+
return screenshot;
|
|
16
|
+
};
|
|
17
|
+
const delayIfNeeded = async (lastResponseTime) => {
|
|
18
|
+
if (lastResponseTime == null) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const currentTime = Date.now();
|
|
22
|
+
const difference = currentTime - lastResponseTime;
|
|
23
|
+
if (difference < 1500) {
|
|
24
|
+
await delay(difference);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
class GptDriver {
|
|
29
|
+
apiKey;
|
|
30
|
+
baseUrl;
|
|
31
|
+
driver;
|
|
32
|
+
deviceConfig;
|
|
33
|
+
firestoreSessionId;
|
|
34
|
+
deviceSize;
|
|
35
|
+
lastCommandExecutionTime;
|
|
36
|
+
constructor(config) {
|
|
37
|
+
this.apiKey = config.apiKey;
|
|
38
|
+
this.baseUrl = "https://api.mobileboost.io";
|
|
39
|
+
if (config.driver !== void 0) {
|
|
40
|
+
this.driver = config.driver;
|
|
41
|
+
} else if (config.deviceConfig !== void 0) {
|
|
42
|
+
this.deviceConfig = config.deviceConfig;
|
|
43
|
+
} else {
|
|
44
|
+
throw new Error("Either provide an appium driver or a deviceConfig object");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async startSession() {
|
|
48
|
+
if (this.driver == void 0 && this.deviceConfig != void 0) {
|
|
49
|
+
const capabilities = {
|
|
50
|
+
platformName: this.deviceConfig.platform,
|
|
51
|
+
"appium:automationName": this.deviceConfig.platform === "Android" ? "UiAutomator2" : "XCUITest",
|
|
52
|
+
"appium:deviceName": this.deviceConfig.deviceName
|
|
53
|
+
};
|
|
54
|
+
const wdOpts = {
|
|
55
|
+
hostname: process.env.APPIUM_HOST || "localhost",
|
|
56
|
+
port: process.env.APPIUM_PORT != null ? parseInt(process.env.APPIUM_PORT, 10) : 4723,
|
|
57
|
+
logLevel: "info",
|
|
58
|
+
capabilities
|
|
59
|
+
};
|
|
60
|
+
this.driver = await remote(wdOpts);
|
|
61
|
+
}
|
|
62
|
+
const driver = this.driver;
|
|
63
|
+
const response = await axios.post(
|
|
64
|
+
`${this.baseUrl}/sessions/create`,
|
|
65
|
+
{
|
|
66
|
+
api_key: this.apiKey,
|
|
67
|
+
appium_session_id: driver.sessionId,
|
|
68
|
+
device_config: {
|
|
69
|
+
// @ts-ignore
|
|
70
|
+
platform: driver.capabilities.platformName,
|
|
71
|
+
// @ts-ignore
|
|
72
|
+
device: driver.capabilities.deviceName,
|
|
73
|
+
// @ts-ignore
|
|
74
|
+
os: driver.capabilities.platformVersion
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
const rect = await driver.getWindowRect();
|
|
79
|
+
this.deviceSize = { width: rect.width, height: rect.height };
|
|
80
|
+
this.firestoreSessionId = response.data.sessionId;
|
|
81
|
+
}
|
|
82
|
+
async stopSession({ status }) {
|
|
83
|
+
await axios.post(
|
|
84
|
+
`${this.baseUrl}/sessions/${this.firestoreSessionId}/stop`,
|
|
85
|
+
{
|
|
86
|
+
api_key: this.apiKey,
|
|
87
|
+
status
|
|
88
|
+
}
|
|
89
|
+
);
|
|
90
|
+
this.firestoreSessionId = void 0;
|
|
91
|
+
}
|
|
92
|
+
async execute(command, appiumHandler) {
|
|
93
|
+
const driver = this.driver;
|
|
94
|
+
if (appiumHandler != null) {
|
|
95
|
+
try {
|
|
96
|
+
await appiumHandler(driver);
|
|
97
|
+
} catch (e) {
|
|
98
|
+
await this.gptHandler(command);
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
await this.gptHandler(command);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async gptHandler(command) {
|
|
105
|
+
const driver = this.driver;
|
|
106
|
+
try {
|
|
107
|
+
let conditionSucceeded = false;
|
|
108
|
+
while (!conditionSucceeded) {
|
|
109
|
+
await delayIfNeeded(this.lastCommandExecutionTime);
|
|
110
|
+
const screenshot = await getScreenshot(driver, this.deviceSize);
|
|
111
|
+
const response = await axios.request(
|
|
112
|
+
{
|
|
113
|
+
url: `${this.baseUrl}/sessions/${this.firestoreSessionId}/execute`,
|
|
114
|
+
method: "POST",
|
|
115
|
+
data: {
|
|
116
|
+
api_key: this.apiKey,
|
|
117
|
+
command,
|
|
118
|
+
base64_screenshot: screenshot
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
const executeStatus = response.data.status;
|
|
123
|
+
if (executeStatus === "failed") {
|
|
124
|
+
throw new Error("Execution failed");
|
|
125
|
+
}
|
|
126
|
+
conditionSucceeded = executeStatus !== "inProgress";
|
|
127
|
+
const executeResponse = response.data;
|
|
128
|
+
for (const command2 of executeResponse.commands) {
|
|
129
|
+
await this.executeCommand(command2);
|
|
130
|
+
}
|
|
131
|
+
this.lastCommandExecutionTime = Date.now();
|
|
132
|
+
}
|
|
133
|
+
} catch (e) {
|
|
134
|
+
await this.stopSession({ status: "failed" });
|
|
135
|
+
throw e;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async executeCommand(command) {
|
|
139
|
+
const firstAction = command.data.actions?.at(0);
|
|
140
|
+
if (firstAction?.type === "pause" && firstAction.duration != null) {
|
|
141
|
+
await delay(firstAction * 1e3);
|
|
142
|
+
} else {
|
|
143
|
+
await axios.request({
|
|
144
|
+
url: command.url,
|
|
145
|
+
method: command.method,
|
|
146
|
+
data: command.data
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export { GptDriver as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gpt-driver-node",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.2",
|
|
4
4
|
"main": "./dist/index.cjs",
|
|
5
5
|
"module": "./dist/index.mjs",
|
|
6
6
|
"types": "./dist/index.d.cts",
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
"license": "CC BY-NC-SA 4.0",
|
|
16
16
|
"description": "Test your mobile apps with the AI native GPT Driver (docs.mobileboost.io).",
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"appium-xcuitest-driver": "^7.24.14",
|
|
19
18
|
"axios": "^1.7.3",
|
|
20
19
|
"sharp": "^0.33.4",
|
|
21
20
|
"webdriverio": "^8.40.0"
|
package/tsconfig.json
CHANGED
package/src/helpers.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import sharp from "sharp";
|
|
2
|
-
|
|
3
|
-
const delay = async (milliseconds: number): Promise<void> => {
|
|
4
|
-
await new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const getScreenshot = async (driver: WebdriverIO.Browser, deviceSize: DeviceSize) => {
|
|
9
|
-
let screenshot = await driver.takeScreenshot();
|
|
10
|
-
if (driver.capabilities.platformName === "iOS") {
|
|
11
|
-
const imageBuffer = Buffer.from(screenshot, 'base64');
|
|
12
|
-
const transformedImage = await sharp(imageBuffer).resize(deviceSize.width, deviceSize.height).toBuffer()
|
|
13
|
-
screenshot = transformedImage.toString('base64')
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
return screenshot;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const delayIfNeeded = async (lastResponseTime?: number) => {
|
|
20
|
-
if (lastResponseTime == null) {
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
const currentTime = Date.now();
|
|
24
|
-
const difference = currentTime - lastResponseTime;
|
|
25
|
-
|
|
26
|
-
if (difference < 1500) {
|
|
27
|
-
await delay(difference);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export {delay, getScreenshot, delayIfNeeded}
|
package/src/index.ts
DELETED
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
import axios from "axios";
|
|
2
|
-
import {remote, RemoteOptions} from 'webdriverio'
|
|
3
|
-
import {delay, delayIfNeeded, getScreenshot} from "./helpers";
|
|
4
|
-
import {AppiumHandler, Command, DeviceConfig, DeviceSize, ExecuteResponse, GptDriverConfig} from "./types";
|
|
5
|
-
|
|
6
|
-
class GptDriver {
|
|
7
|
-
apiKey: string;
|
|
8
|
-
baseUrl: string;
|
|
9
|
-
driver?: WebdriverIO.Browser;
|
|
10
|
-
deviceConfig?: DeviceConfig;
|
|
11
|
-
firestoreSessionId?: string;
|
|
12
|
-
deviceSize?: DeviceSize;
|
|
13
|
-
lastCommandExecutionTime?: number;
|
|
14
|
-
|
|
15
|
-
constructor(config: GptDriverConfig) {
|
|
16
|
-
this.apiKey = config.apiKey;
|
|
17
|
-
this.baseUrl = "https://api.mobileboost.io";
|
|
18
|
-
|
|
19
|
-
if (config.driver !== undefined) {
|
|
20
|
-
this.driver = config.driver
|
|
21
|
-
} else if (config.deviceConfig !== undefined) {
|
|
22
|
-
this.deviceConfig = config.deviceConfig;
|
|
23
|
-
} else {
|
|
24
|
-
throw new Error("Either provide an appium driver or a deviceConfig object")
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async startSession() {
|
|
29
|
-
if (this.driver == undefined && this.deviceConfig != undefined) {
|
|
30
|
-
const capabilities = {
|
|
31
|
-
platformName: this.deviceConfig.platform,
|
|
32
|
-
'appium:automationName': this.deviceConfig.platform === "Android" ? 'UiAutomator2' : "XCUITest",
|
|
33
|
-
'appium:deviceName': this.deviceConfig.deviceName,
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const wdOpts: RemoteOptions = {
|
|
37
|
-
hostname: process.env.APPIUM_HOST || 'localhost',
|
|
38
|
-
port: process.env.APPIUM_PORT != null ? parseInt(process.env.APPIUM_PORT, 10) : 4723,
|
|
39
|
-
logLevel: 'info',
|
|
40
|
-
capabilities: capabilities,
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
this.driver = await remote(wdOpts);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const driver = this.driver!;
|
|
48
|
-
|
|
49
|
-
const response = await axios.post(
|
|
50
|
-
`${this.baseUrl}/sessions/create`,
|
|
51
|
-
{
|
|
52
|
-
api_key: this.apiKey,
|
|
53
|
-
appium_session_id: driver.sessionId,
|
|
54
|
-
device_config: {
|
|
55
|
-
// @ts-ignore
|
|
56
|
-
platform: driver.capabilities.platformName,
|
|
57
|
-
// @ts-ignore
|
|
58
|
-
device: driver.capabilities.deviceName,
|
|
59
|
-
// @ts-ignore
|
|
60
|
-
os: driver.capabilities.platformVersion
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
)
|
|
64
|
-
const rect = await driver.getWindowRect();
|
|
65
|
-
this.deviceSize = {width: rect.width, height: rect.height}
|
|
66
|
-
|
|
67
|
-
this.firestoreSessionId = response.data.sessionId;
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
async stopSession({status}: { status: "failed" | "success" }) {
|
|
72
|
-
await axios.post(
|
|
73
|
-
`${this.baseUrl}/sessions/${this.firestoreSessionId}/stop`,
|
|
74
|
-
{
|
|
75
|
-
api_key: this.apiKey,
|
|
76
|
-
status,
|
|
77
|
-
},
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
this.firestoreSessionId = undefined;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async execute(command: string, appiumHandler?: AppiumHandler) {
|
|
84
|
-
const driver = this.driver!;
|
|
85
|
-
|
|
86
|
-
if (appiumHandler != null) {
|
|
87
|
-
try {
|
|
88
|
-
await appiumHandler(driver);
|
|
89
|
-
} catch (e) {
|
|
90
|
-
await this.gptHandler(command)
|
|
91
|
-
}
|
|
92
|
-
} else {
|
|
93
|
-
await this.gptHandler(command)
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
private async gptHandler(command: string) {
|
|
98
|
-
const driver = this.driver!;
|
|
99
|
-
|
|
100
|
-
try {
|
|
101
|
-
let conditionSucceeded = false;
|
|
102
|
-
|
|
103
|
-
while (!conditionSucceeded) {
|
|
104
|
-
await delayIfNeeded(this.lastCommandExecutionTime);
|
|
105
|
-
const screenshot = await getScreenshot(driver, this.deviceSize!)
|
|
106
|
-
|
|
107
|
-
const response = await axios.request({
|
|
108
|
-
url: `${this.baseUrl}/sessions/${this.firestoreSessionId}/execute`,
|
|
109
|
-
method: "POST",
|
|
110
|
-
data: {
|
|
111
|
-
api_key: this.apiKey,
|
|
112
|
-
command,
|
|
113
|
-
base64_screenshot: screenshot,
|
|
114
|
-
},
|
|
115
|
-
}
|
|
116
|
-
)
|
|
117
|
-
const executeStatus = response.data.status;
|
|
118
|
-
if (executeStatus === "failed") {
|
|
119
|
-
throw new Error("Execution failed");
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
conditionSucceeded = executeStatus !== "inProgress";
|
|
123
|
-
const executeResponse: ExecuteResponse = response.data;
|
|
124
|
-
for (const command of executeResponse.commands) {
|
|
125
|
-
await this.executeCommand(command)
|
|
126
|
-
}
|
|
127
|
-
this.lastCommandExecutionTime = Date.now();
|
|
128
|
-
}
|
|
129
|
-
} catch (e) {
|
|
130
|
-
await this.stopSession({status: "failed"})
|
|
131
|
-
throw e;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
private async executeCommand(command: Command) {
|
|
137
|
-
const firstAction = command.data.actions?.at(0);
|
|
138
|
-
if (firstAction?.type === "pause" && firstAction.duration != null) {
|
|
139
|
-
await delay(firstAction * 1000)
|
|
140
|
-
} else {
|
|
141
|
-
await axios.request({
|
|
142
|
-
url: command.url,
|
|
143
|
-
method: command.method,
|
|
144
|
-
data: command.data
|
|
145
|
-
})
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export default GptDriver;
|
package/src/types.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
interface ExecuteResponse {
|
|
2
|
-
commands: Command[]
|
|
3
|
-
status: "inProgress" | "success" | "failed"
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
interface Command {
|
|
7
|
-
method: 'GET' | 'DELETE' | 'POST';
|
|
8
|
-
url: string;
|
|
9
|
-
data: any;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
interface AppiumHandler {
|
|
13
|
-
(driver: WebdriverIO.Browser): Promise<any>;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
interface DeviceConfig {
|
|
17
|
-
platform: "iOS" | "Android";
|
|
18
|
-
deviceName?: string;
|
|
19
|
-
platformVersion?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
interface GptDriverConfig {
|
|
23
|
-
apiKey: string;
|
|
24
|
-
driver?: WebdriverIO.Browser;
|
|
25
|
-
deviceConfig?: DeviceConfig;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
interface DeviceSize {
|
|
29
|
-
width: number,
|
|
30
|
-
height: number
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export type {ExecuteResponse, Command, AppiumHandler, DeviceConfig, GptDriverConfig, DeviceSize}
|