@stubber/virtual-worker 1.2.0 → 1.4.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/app/commands/api_proxy/api_proxy.js +74 -0
- package/app/commands/browser/browser_click.js +1 -1
- package/app/commands/browser/browser_extract_data.js +1 -1
- package/app/commands/browser/browser_extract_html.js +1 -1
- package/app/commands/browser/browser_get_clipboard_text.js +1 -1
- package/app/commands/browser/browser_get_localstorage.js +1 -1
- package/app/commands/browser/browser_navigate.js +1 -1
- package/app/commands/browser/browser_press_key.js +1 -1
- package/app/commands/browser/browser_screenshot.js +2 -2
- package/app/commands/browser/browser_write_text.js +1 -1
- package/app/commands/file-server/upload_files.js +7 -0
- package/app/commands/index.js +4 -0
- package/app/helpers/get_chromium_page.js +7 -2
- package/lib/interfaces/http/routers/task_gateway.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { create_success } from "#app/functions/create_success.js";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
|
|
4
|
+
const return_data_schema = z.object({
|
|
5
|
+
// eslint-disable-next-line id-match
|
|
6
|
+
contentType: z.string(),
|
|
7
|
+
body: z.any(),
|
|
8
|
+
status: z.number(),
|
|
9
|
+
// eslint-disable-next-line id-match
|
|
10
|
+
statusText: z.string(),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const params_schema = z.looseObject({
|
|
14
|
+
apiurl: z.string(),
|
|
15
|
+
options: z.looseObject({}).optional(),
|
|
16
|
+
timeout_seconds: z.number().optional(),
|
|
17
|
+
__apicall_params: z
|
|
18
|
+
.looseObject({})
|
|
19
|
+
.optional()
|
|
20
|
+
.describe("apicall params as originally passed to the apicall task on core"),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Run an arbitrary CLI command and return stdout/stderr.
|
|
25
|
+
* @param {z.infer<typeof params_schema>} params
|
|
26
|
+
*/
|
|
27
|
+
export const api_proxy = async (params, _stubber) => {
|
|
28
|
+
let { apiurl, options, timeout_seconds, __apicall_params } = params || {};
|
|
29
|
+
|
|
30
|
+
const timeout = (timeout_seconds || __apicall_params?.timeout_seconds || 15) * 1000;
|
|
31
|
+
|
|
32
|
+
if (!options) {
|
|
33
|
+
options = {};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// console.log("timeout", timeout);
|
|
37
|
+
|
|
38
|
+
options.signal = AbortSignal.timeout(timeout);
|
|
39
|
+
|
|
40
|
+
const response = await fetch(apiurl, options);
|
|
41
|
+
|
|
42
|
+
const content_type = response.headers.get("content-type") || "";
|
|
43
|
+
let body;
|
|
44
|
+
if (content_type.includes("application/json")) {
|
|
45
|
+
body = await response.json();
|
|
46
|
+
} else if (content_type.includes("multipart/form-data")) {
|
|
47
|
+
body = await response.formData();
|
|
48
|
+
} else if (content_type.includes("application/octet-stream")) {
|
|
49
|
+
body = await response.blob();
|
|
50
|
+
} else {
|
|
51
|
+
body = await response.text();
|
|
52
|
+
}
|
|
53
|
+
const status = response.status;
|
|
54
|
+
const status_text = response.statusText;
|
|
55
|
+
|
|
56
|
+
/** @type {z.infer<typeof return_data_schema>} */
|
|
57
|
+
const result = {
|
|
58
|
+
// eslint-disable-next-line id-match
|
|
59
|
+
contentType: content_type,
|
|
60
|
+
body: body || undefined,
|
|
61
|
+
status,
|
|
62
|
+
// eslint-disable-next-line id-match
|
|
63
|
+
statusText: status_text,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const success = response.ok;
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
success,
|
|
70
|
+
payload: {
|
|
71
|
+
apiresult: result,
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
};
|
|
@@ -15,7 +15,7 @@ export const browser_click = async (params, stubber_context) => {
|
|
|
15
15
|
const { entries } = params || {};
|
|
16
16
|
|
|
17
17
|
// use playwright to move the mouse and perform a left click
|
|
18
|
-
const page_result = await get_chromium_page(params
|
|
18
|
+
const page_result = await get_chromium_page(params, stubber_context);
|
|
19
19
|
|
|
20
20
|
if (!page_result.success) {
|
|
21
21
|
return page_result;
|
|
@@ -9,7 +9,7 @@ export const browser_extract_data = async (params, stubber_context) => {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
// Get the Chromium page
|
|
12
|
-
const page_result = await get_chromium_page(params
|
|
12
|
+
const page_result = await get_chromium_page(params, stubber_context);
|
|
13
13
|
if (!page_result.success) {
|
|
14
14
|
return page_result;
|
|
15
15
|
}
|
|
@@ -10,7 +10,7 @@ import { get_chromium_page } from "../../helpers/get_chromium_page.js";
|
|
|
10
10
|
*/
|
|
11
11
|
export const browser_extract_html = async (params, stubber_context) => {
|
|
12
12
|
// Get the Chromium page
|
|
13
|
-
const page_result = await get_chromium_page(params
|
|
13
|
+
const page_result = await get_chromium_page(params, stubber_context);
|
|
14
14
|
if (!page_result.success) {
|
|
15
15
|
return page_result;
|
|
16
16
|
}
|
|
@@ -13,7 +13,7 @@ import { get_chromium_page } from "../../helpers/get_chromium_page.js";
|
|
|
13
13
|
* @returns
|
|
14
14
|
*/
|
|
15
15
|
export const browser_get_clipboard_text = async (params, stubber_context) => {
|
|
16
|
-
const page_result = await get_chromium_page(params
|
|
16
|
+
const page_result = await get_chromium_page(params, stubber_context);
|
|
17
17
|
|
|
18
18
|
if (!page_result.success) {
|
|
19
19
|
return page_result;
|
|
@@ -3,7 +3,7 @@ import { create_success } from "#app/functions/create_success.js";
|
|
|
3
3
|
import { get_chromium_page } from "../../helpers/get_chromium_page.js";
|
|
4
4
|
|
|
5
5
|
export const browser_get_localstorage = async (params, stubber_context) => {
|
|
6
|
-
const page_result = await get_chromium_page(params
|
|
6
|
+
const page_result = await get_chromium_page(params, stubber_context);
|
|
7
7
|
|
|
8
8
|
if (!page_result.success) {
|
|
9
9
|
return page_result;
|
|
@@ -3,7 +3,7 @@ import { create_success } from "#app/functions/create_success.js";
|
|
|
3
3
|
import { get_chromium_page } from "../../helpers/get_chromium_page.js";
|
|
4
4
|
|
|
5
5
|
export const browser_navigate = async (params, stubber_context) => {
|
|
6
|
-
const result = await get_chromium_page(params
|
|
6
|
+
const result = await get_chromium_page(params, stubber_context);
|
|
7
7
|
if (!result.success) {
|
|
8
8
|
return result;
|
|
9
9
|
}
|
|
@@ -11,7 +11,7 @@ import { get_chromium_page } from "#app/helpers/get_chromium_page.js";
|
|
|
11
11
|
*/
|
|
12
12
|
export const browser_press_key = async (params, stubber_context) => {
|
|
13
13
|
const { entries } = params || {};
|
|
14
|
-
const page_result = await get_chromium_page(params
|
|
14
|
+
const page_result = await get_chromium_page(params, stubber_context);
|
|
15
15
|
if (!page_result.success) {
|
|
16
16
|
return page_result;
|
|
17
17
|
}
|
|
@@ -14,7 +14,7 @@ import { create_error_technical } from "#app/functions/create_error_technical.js
|
|
|
14
14
|
export const browser_screenshot = async (params, stubber_context) => {
|
|
15
15
|
let { screenshot_options, locator } = params || {};
|
|
16
16
|
|
|
17
|
-
const page_result = await get_chromium_page(params
|
|
17
|
+
const page_result = await get_chromium_page(params, stubber_context);
|
|
18
18
|
if (!page_result.success) {
|
|
19
19
|
return page_result;
|
|
20
20
|
}
|
|
@@ -53,7 +53,7 @@ export const browser_screenshot = async (params, stubber_context) => {
|
|
|
53
53
|
|
|
54
54
|
return create_success({
|
|
55
55
|
message: "Screenshot captured successfully",
|
|
56
|
-
payload: { screenshot: { path: screenshot_options.path, file_info } },
|
|
56
|
+
payload: { screenshot: { path: screenshot_options.path, file_info }, attachments: file_info ? [file_info] : [] },
|
|
57
57
|
});
|
|
58
58
|
} catch (error) {
|
|
59
59
|
return create_error_technical(error);
|
|
@@ -11,7 +11,7 @@ import { get_chromium_page } from "../../helpers/get_chromium_page.js";
|
|
|
11
11
|
*/
|
|
12
12
|
export const browser_write_text = async (params, stubber_context) => {
|
|
13
13
|
const { entries } = params || {};
|
|
14
|
-
const page_result = await get_chromium_page(params
|
|
14
|
+
const page_result = await get_chromium_page(params, stubber_context);
|
|
15
15
|
if (!page_result.success) {
|
|
16
16
|
return page_result;
|
|
17
17
|
}
|
|
@@ -98,9 +98,16 @@ export const upload_files = async (params, _stubber) => {
|
|
|
98
98
|
};
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
let attachments = [];
|
|
102
|
+
|
|
103
|
+
if (payload.uploaded_files) {
|
|
104
|
+
attachments = payload.uploaded_files;
|
|
105
|
+
}
|
|
106
|
+
|
|
101
107
|
return create_success({
|
|
102
108
|
message: "Files uploaded successfully",
|
|
103
109
|
payload,
|
|
110
|
+
attachments,
|
|
104
111
|
});
|
|
105
112
|
} catch (error) {
|
|
106
113
|
return create_error_technical(error);
|
package/app/commands/index.js
CHANGED
|
@@ -12,6 +12,8 @@ import { cli_run } from "./cli/cli_run.js";
|
|
|
12
12
|
import { upload_files } from "./file-server/upload_files.js";
|
|
13
13
|
import { download_files } from "./file-server/download_files.js";
|
|
14
14
|
|
|
15
|
+
import { api_proxy } from "./api_proxy/api_proxy.js";
|
|
16
|
+
|
|
15
17
|
const all_commands = {
|
|
16
18
|
browser_click,
|
|
17
19
|
browser_extract_data,
|
|
@@ -27,6 +29,8 @@ const all_commands = {
|
|
|
27
29
|
|
|
28
30
|
upload_files,
|
|
29
31
|
download_files,
|
|
32
|
+
|
|
33
|
+
api_proxy,
|
|
30
34
|
};
|
|
31
35
|
|
|
32
36
|
export { all_commands };
|
|
@@ -16,17 +16,22 @@ const contexts = {};
|
|
|
16
16
|
* @param {string} session_id
|
|
17
17
|
* @returns {Promise<{ success: boolean, payload?: import("playwright").Page }>}
|
|
18
18
|
*/
|
|
19
|
-
export const get_chromium_page = async (
|
|
19
|
+
export const get_chromium_page = async (params, stubber_context) => {
|
|
20
|
+
const session_id = params?.session_id || stubber_context.stubref;
|
|
20
21
|
if (!session_id) {
|
|
21
22
|
return create_error_conceptual({ message: "session_id is required to get a Chromium page." });
|
|
22
23
|
}
|
|
23
24
|
|
|
25
|
+
const slow_mo = params?.slow_mo || process.env.SLOW_MO || 0;
|
|
26
|
+
|
|
27
|
+
console.log(`get_chromium_page: session_id=${session_id}, slow_mo=${slow_mo}`);
|
|
28
|
+
|
|
24
29
|
// Launch the browser once and reuse it
|
|
25
30
|
if (!browser) {
|
|
26
31
|
browser = await chromium.launch({
|
|
27
32
|
headless: false,
|
|
28
33
|
// eslint-disable-next-line id-match
|
|
29
|
-
slowMo:
|
|
34
|
+
slowMo: slow_mo,
|
|
30
35
|
});
|
|
31
36
|
}
|
|
32
37
|
|
|
@@ -15,7 +15,7 @@ router.post(["/virtual_worker_task", "/virtual_worker_send_commands"], async (re
|
|
|
15
15
|
const payload = task_payload_schema.parse(req.body);
|
|
16
16
|
const task = payload.task;
|
|
17
17
|
|
|
18
|
-
console.log("Received task:", task.task_name, "of type:", task.tasktype
|
|
18
|
+
console.log("Received task:", task.task_name, "of type:", task.tasktype);
|
|
19
19
|
|
|
20
20
|
const result = await virtual_worker_task(task);
|
|
21
21
|
|