@godscene/shared 1.7.11
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 +9 -0
- package/dist/es/baseDB.mjs +109 -0
- package/dist/es/cli/cli-args.mjs +95 -0
- package/dist/es/cli/cli-error.mjs +24 -0
- package/dist/es/cli/cli-runner.mjs +122 -0
- package/dist/es/cli/index.mjs +4 -0
- package/dist/es/common.mjs +37 -0
- package/dist/es/constants/example-code.mjs +227 -0
- package/dist/es/constants/index.mjs +124 -0
- package/dist/es/env/basic.mjs +6 -0
- package/dist/es/env/constants.mjs +110 -0
- package/dist/es/env/global-config-manager.mjs +94 -0
- package/dist/es/env/helper.mjs +43 -0
- package/dist/es/env/index.mjs +5 -0
- package/dist/es/env/init-debug.mjs +18 -0
- package/dist/es/env/model-config-manager.mjs +79 -0
- package/dist/es/env/parse-model-config.mjs +165 -0
- package/dist/es/env/types.mjs +232 -0
- package/dist/es/env/utils.mjs +18 -0
- package/dist/es/extractor/constants.mjs +2 -0
- package/dist/es/extractor/cs_postmessage.mjs +61 -0
- package/dist/es/extractor/customLocator.mjs +641 -0
- package/dist/es/extractor/debug.mjs +6 -0
- package/dist/es/extractor/dom-util.mjs +96 -0
- package/dist/es/extractor/index.mjs +5 -0
- package/dist/es/extractor/locator.mjs +250 -0
- package/dist/es/extractor/tree.mjs +78 -0
- package/dist/es/extractor/util.mjs +245 -0
- package/dist/es/extractor/web-extractor.mjs +393 -0
- package/dist/es/img/box-select.mjs +824 -0
- package/dist/es/img/canvas-fallback.mjs +238 -0
- package/dist/es/img/get-photon.mjs +45 -0
- package/dist/es/img/get-sharp.mjs +11 -0
- package/dist/es/img/index.mjs +4 -0
- package/dist/es/img/info.mjs +35 -0
- package/dist/es/img/transform.mjs +275 -0
- package/dist/es/index.mjs +2 -0
- package/dist/es/key-alias-utils.mjs +19 -0
- package/dist/es/logger.mjs +64 -0
- package/dist/es/mcp/base-server.mjs +282 -0
- package/dist/es/mcp/base-tools.mjs +159 -0
- package/dist/es/mcp/chrome-path.mjs +35 -0
- package/dist/es/mcp/cli-report-session.mjs +78 -0
- package/dist/es/mcp/error-formatter.mjs +19 -0
- package/dist/es/mcp/index.mjs +9 -0
- package/dist/es/mcp/init-arg-utils.mjs +38 -0
- package/dist/es/mcp/inject-report-html-plugin.mjs +53 -0
- package/dist/es/mcp/launcher-helper.mjs +52 -0
- package/dist/es/mcp/tool-generator.mjs +419 -0
- package/dist/es/mcp/types.mjs +3 -0
- package/dist/es/node/fs.mjs +44 -0
- package/dist/es/node/index.mjs +2 -0
- package/dist/es/node/port.mjs +24 -0
- package/dist/es/polyfills/async-hooks.mjs +2 -0
- package/dist/es/polyfills/index.mjs +1 -0
- package/dist/es/types/index.mjs +3 -0
- package/dist/es/us-keyboard-layout.mjs +1414 -0
- package/dist/es/us-keyboard-layout.mjs.LICENSE.txt +5 -0
- package/dist/es/utils.mjs +72 -0
- package/dist/es/zod-schema-utils.mjs +54 -0
- package/dist/lib/baseDB.js +149 -0
- package/dist/lib/cli/cli-args.js +138 -0
- package/dist/lib/cli/cli-error.js +61 -0
- package/dist/lib/cli/cli-runner.js +181 -0
- package/dist/lib/cli/index.js +53 -0
- package/dist/lib/common.js +93 -0
- package/dist/lib/constants/example-code.js +264 -0
- package/dist/lib/constants/index.js +221 -0
- package/dist/lib/env/basic.js +40 -0
- package/dist/lib/env/constants.js +153 -0
- package/dist/lib/env/global-config-manager.js +128 -0
- package/dist/lib/env/helper.js +80 -0
- package/dist/lib/env/index.js +90 -0
- package/dist/lib/env/init-debug.js +52 -0
- package/dist/lib/env/model-config-manager.js +113 -0
- package/dist/lib/env/parse-model-config.js +211 -0
- package/dist/lib/env/types.js +572 -0
- package/dist/lib/env/utils.js +61 -0
- package/dist/lib/extractor/constants.js +42 -0
- package/dist/lib/extractor/cs_postmessage.js +98 -0
- package/dist/lib/extractor/customLocator.js +693 -0
- package/dist/lib/extractor/debug.js +12 -0
- package/dist/lib/extractor/dom-util.js +157 -0
- package/dist/lib/extractor/index.js +87 -0
- package/dist/lib/extractor/locator.js +296 -0
- package/dist/lib/extractor/tree.js +124 -0
- package/dist/lib/extractor/util.js +336 -0
- package/dist/lib/extractor/web-extractor.js +442 -0
- package/dist/lib/img/box-select.js +875 -0
- package/dist/lib/img/canvas-fallback.js +305 -0
- package/dist/lib/img/get-photon.js +82 -0
- package/dist/lib/img/get-sharp.js +45 -0
- package/dist/lib/img/index.js +95 -0
- package/dist/lib/img/info.js +92 -0
- package/dist/lib/img/transform.js +364 -0
- package/dist/lib/index.js +36 -0
- package/dist/lib/key-alias-utils.js +62 -0
- package/dist/lib/logger.js +114 -0
- package/dist/lib/mcp/base-server.js +332 -0
- package/dist/lib/mcp/base-tools.js +193 -0
- package/dist/lib/mcp/chrome-path.js +72 -0
- package/dist/lib/mcp/cli-report-session.js +121 -0
- package/dist/lib/mcp/error-formatter.js +53 -0
- package/dist/lib/mcp/index.js +114 -0
- package/dist/lib/mcp/init-arg-utils.js +78 -0
- package/dist/lib/mcp/inject-report-html-plugin.js +98 -0
- package/dist/lib/mcp/launcher-helper.js +86 -0
- package/dist/lib/mcp/tool-generator.js +456 -0
- package/dist/lib/mcp/types.js +40 -0
- package/dist/lib/node/fs.js +97 -0
- package/dist/lib/node/index.js +65 -0
- package/dist/lib/node/port.js +61 -0
- package/dist/lib/polyfills/async-hooks.js +36 -0
- package/dist/lib/polyfills/index.js +58 -0
- package/dist/lib/types/index.js +37 -0
- package/dist/lib/us-keyboard-layout.js +1457 -0
- package/dist/lib/us-keyboard-layout.js.LICENSE.txt +5 -0
- package/dist/lib/utils.js +148 -0
- package/dist/lib/zod-schema-utils.js +97 -0
- package/dist/types/baseDB.d.ts +25 -0
- package/dist/types/cli/cli-args.d.ts +8 -0
- package/dist/types/cli/cli-error.d.ts +5 -0
- package/dist/types/cli/cli-runner.d.ts +19 -0
- package/dist/types/cli/index.d.ts +4 -0
- package/dist/types/common.d.ts +12 -0
- package/dist/types/constants/example-code.d.ts +2 -0
- package/dist/types/constants/index.d.ts +61 -0
- package/dist/types/env/basic.d.ts +6 -0
- package/dist/types/env/constants.d.ts +50 -0
- package/dist/types/env/global-config-manager.d.ts +32 -0
- package/dist/types/env/helper.d.ts +4 -0
- package/dist/types/env/index.d.ts +4 -0
- package/dist/types/env/init-debug.d.ts +1 -0
- package/dist/types/env/model-config-manager.d.ts +25 -0
- package/dist/types/env/parse-model-config.d.ts +31 -0
- package/dist/types/env/types.d.ts +339 -0
- package/dist/types/env/utils.d.ts +7 -0
- package/dist/types/extractor/constants.d.ts +1 -0
- package/dist/types/extractor/cs_postmessage.d.ts +2 -0
- package/dist/types/extractor/customLocator.d.ts +69 -0
- package/dist/types/extractor/debug.d.ts +1 -0
- package/dist/types/extractor/dom-util.d.ts +57 -0
- package/dist/types/extractor/index.d.ts +33 -0
- package/dist/types/extractor/locator.d.ts +9 -0
- package/dist/types/extractor/tree.d.ts +6 -0
- package/dist/types/extractor/util.d.ts +47 -0
- package/dist/types/extractor/web-extractor.d.ts +24 -0
- package/dist/types/img/box-select.d.ts +26 -0
- package/dist/types/img/canvas-fallback.d.ts +105 -0
- package/dist/types/img/get-photon.d.ts +19 -0
- package/dist/types/img/get-sharp.d.ts +3 -0
- package/dist/types/img/index.d.ts +3 -0
- package/dist/types/img/info.d.ts +34 -0
- package/dist/types/img/transform.d.ts +98 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/key-alias-utils.d.ts +9 -0
- package/dist/types/logger.d.ts +5 -0
- package/dist/types/mcp/base-server.d.ts +93 -0
- package/dist/types/mcp/base-tools.d.ts +148 -0
- package/dist/types/mcp/chrome-path.d.ts +2 -0
- package/dist/types/mcp/cli-report-session.d.ts +12 -0
- package/dist/types/mcp/error-formatter.d.ts +12 -0
- package/dist/types/mcp/index.d.ts +9 -0
- package/dist/types/mcp/init-arg-utils.d.ts +13 -0
- package/dist/types/mcp/inject-report-html-plugin.d.ts +18 -0
- package/dist/types/mcp/launcher-helper.d.ts +94 -0
- package/dist/types/mcp/tool-generator.d.ts +10 -0
- package/dist/types/mcp/types.d.ts +113 -0
- package/dist/types/node/fs.d.ts +15 -0
- package/dist/types/node/index.d.ts +2 -0
- package/dist/types/node/port.d.ts +8 -0
- package/dist/types/polyfills/async-hooks.d.ts +6 -0
- package/dist/types/polyfills/index.d.ts +4 -0
- package/dist/types/types/index.d.ts +36 -0
- package/dist/types/us-keyboard-layout.d.ts +32 -0
- package/dist/types/utils.d.ts +34 -0
- package/dist/types/zod-schema-utils.d.ts +23 -0
- package/package.json +125 -0
- package/src/baseDB.ts +158 -0
- package/src/cli/cli-args.ts +173 -0
- package/src/cli/cli-error.ts +24 -0
- package/src/cli/cli-runner.ts +230 -0
- package/src/cli/index.ts +4 -0
- package/src/common.ts +67 -0
- package/src/constants/example-code.ts +227 -0
- package/src/constants/index.ts +139 -0
- package/src/env/basic.ts +12 -0
- package/src/env/constants.ts +303 -0
- package/src/env/global-config-manager.ts +191 -0
- package/src/env/helper.ts +58 -0
- package/src/env/index.ts +4 -0
- package/src/env/init-debug.ts +34 -0
- package/src/env/model-config-manager.ts +149 -0
- package/src/env/parse-model-config.ts +357 -0
- package/src/env/types.ts +583 -0
- package/src/env/utils.ts +39 -0
- package/src/extractor/constants.ts +5 -0
- package/src/extractor/cs_postmessage.ts +136 -0
- package/src/extractor/customLocator.ts +1245 -0
- package/src/extractor/debug.ts +10 -0
- package/src/extractor/dom-util.ts +231 -0
- package/src/extractor/index.ts +50 -0
- package/src/extractor/locator.ts +469 -0
- package/src/extractor/tree.ts +179 -0
- package/src/extractor/util.ts +482 -0
- package/src/extractor/web-extractor.ts +617 -0
- package/src/img/box-select.ts +588 -0
- package/src/img/canvas-fallback.ts +393 -0
- package/src/img/get-photon.ts +108 -0
- package/src/img/get-sharp.ts +18 -0
- package/src/img/index.ts +27 -0
- package/src/img/info.ts +102 -0
- package/src/img/transform.ts +553 -0
- package/src/index.ts +1 -0
- package/src/key-alias-utils.ts +23 -0
- package/src/logger.ts +96 -0
- package/src/mcp/base-server.ts +500 -0
- package/src/mcp/base-tools.ts +391 -0
- package/src/mcp/chrome-path.ts +48 -0
- package/src/mcp/cli-report-session.ts +130 -0
- package/src/mcp/error-formatter.ts +52 -0
- package/src/mcp/index.ts +9 -0
- package/src/mcp/init-arg-utils.ts +105 -0
- package/src/mcp/inject-report-html-plugin.ts +119 -0
- package/src/mcp/launcher-helper.ts +200 -0
- package/src/mcp/tool-generator.ts +658 -0
- package/src/mcp/types.ts +131 -0
- package/src/node/fs.ts +84 -0
- package/src/node/index.ts +2 -0
- package/src/node/port.ts +37 -0
- package/src/polyfills/async-hooks.ts +6 -0
- package/src/polyfills/index.ts +4 -0
- package/src/types/index.ts +54 -0
- package/src/us-keyboard-layout.ts +723 -0
- package/src/utils.ts +149 -0
- package/src/zod-schema-utils.ts +133 -0
package/README.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
function _define_property(obj, key, value) {
|
|
2
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
3
|
+
value: value,
|
|
4
|
+
enumerable: true,
|
|
5
|
+
configurable: true,
|
|
6
|
+
writable: true
|
|
7
|
+
});
|
|
8
|
+
else obj[key] = value;
|
|
9
|
+
return obj;
|
|
10
|
+
}
|
|
11
|
+
class IndexedDBManager {
|
|
12
|
+
initDB() {
|
|
13
|
+
return new Promise((resolve, reject)=>{
|
|
14
|
+
const request = indexedDB.open(this.dbName, this.version);
|
|
15
|
+
request.onerror = ()=>reject(request.error);
|
|
16
|
+
request.onsuccess = ()=>resolve(request.result);
|
|
17
|
+
request.onupgradeneeded = (event)=>{
|
|
18
|
+
const db = event.target.result;
|
|
19
|
+
this.storeConfigs.forEach(({ name, keyPath })=>{
|
|
20
|
+
if (!db.objectStoreNames.contains(name)) {
|
|
21
|
+
const store = db.createObjectStore(name, {
|
|
22
|
+
keyPath
|
|
23
|
+
});
|
|
24
|
+
store.createIndex('timestamp', 'timestamp', {
|
|
25
|
+
unique: false
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
async withTransaction(storeNames, mode, operation) {
|
|
33
|
+
const db = await this.dbPromise;
|
|
34
|
+
const transaction = db.transaction(storeNames, mode);
|
|
35
|
+
const stores = Array.isArray(storeNames) ? storeNames.map((name)=>transaction.objectStore(name)) : transaction.objectStore(storeNames);
|
|
36
|
+
return operation(stores);
|
|
37
|
+
}
|
|
38
|
+
promisifyRequest(request) {
|
|
39
|
+
return new Promise((resolve, reject)=>{
|
|
40
|
+
request.onsuccess = ()=>resolve(request.result);
|
|
41
|
+
request.onerror = ()=>reject(request.error);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
async put(storeName, data) {
|
|
45
|
+
await this.withTransaction(storeName, 'readwrite', async (store)=>{
|
|
46
|
+
await this.promisifyRequest(store.put(data));
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
async get(storeName, key) {
|
|
50
|
+
return this.withTransaction(storeName, 'readonly', async (store)=>this.promisifyRequest(store.get(key)));
|
|
51
|
+
}
|
|
52
|
+
async getAll(storeName, sortByTimestamp = true) {
|
|
53
|
+
return this.withTransaction(storeName, 'readonly', async (store)=>{
|
|
54
|
+
const objectStore = store;
|
|
55
|
+
const results = sortByTimestamp ? await this.promisifyRequest(objectStore.index('timestamp').getAll()) : await this.promisifyRequest(objectStore.getAll());
|
|
56
|
+
return sortByTimestamp ? results.sort((a, b)=>a.timestamp - b.timestamp) : results;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
async clear(storeName) {
|
|
60
|
+
await this.withTransaction(storeName, 'readwrite', async (store)=>{
|
|
61
|
+
await this.promisifyRequest(store.clear());
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
async delete(storeName, key) {
|
|
65
|
+
await this.withTransaction(storeName, 'readwrite', async (store)=>{
|
|
66
|
+
await this.promisifyRequest(store.delete(key));
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
async count(storeName) {
|
|
70
|
+
return this.withTransaction(storeName, 'readonly', async (store)=>this.promisifyRequest(store.count()));
|
|
71
|
+
}
|
|
72
|
+
getDBPromise() {
|
|
73
|
+
return this.dbPromise;
|
|
74
|
+
}
|
|
75
|
+
constructor(dbName, version, storeConfigs){
|
|
76
|
+
_define_property(this, "dbPromise", void 0);
|
|
77
|
+
_define_property(this, "dbName", void 0);
|
|
78
|
+
_define_property(this, "version", void 0);
|
|
79
|
+
_define_property(this, "storeConfigs", void 0);
|
|
80
|
+
this.dbName = dbName;
|
|
81
|
+
this.version = version;
|
|
82
|
+
this.storeConfigs = storeConfigs;
|
|
83
|
+
this.dbPromise = this.initDB();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const withErrorHandling = async (operation, errorMessage, defaultValue, onQuotaExceeded)=>{
|
|
87
|
+
try {
|
|
88
|
+
return await operation();
|
|
89
|
+
} catch (e) {
|
|
90
|
+
console.error(errorMessage, e);
|
|
91
|
+
if (e instanceof Error && 'QuotaExceededError' === e.name && onQuotaExceeded) {
|
|
92
|
+
console.log('Storage quota exceeded, running cleanup...');
|
|
93
|
+
await onQuotaExceeded();
|
|
94
|
+
}
|
|
95
|
+
return defaultValue;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
const createCleanupFunction = (dbManager, storeName, maxItems)=>async ()=>{
|
|
99
|
+
try {
|
|
100
|
+
const results = await dbManager.getAll(storeName);
|
|
101
|
+
if (results.length > maxItems) {
|
|
102
|
+
const toDelete = results.sort((a, b)=>a.timestamp - b.timestamp).slice(0, results.length - maxItems);
|
|
103
|
+
await Promise.all(toDelete.map((item)=>dbManager.delete(storeName, item.id)));
|
|
104
|
+
}
|
|
105
|
+
} catch (e) {
|
|
106
|
+
console.error(`Failed to cleanup ${storeName}:`, e);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
export { IndexedDBManager, createCleanupFunction, withErrorHandling };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { getKeyAliases } from "../key-alias-utils.mjs";
|
|
3
|
+
function parseValue(raw) {
|
|
4
|
+
if (raw.startsWith('{') || raw.startsWith('[')) try {
|
|
5
|
+
return JSON.parse(raw);
|
|
6
|
+
} catch {}
|
|
7
|
+
if (/^-?\d+(\.\d+)?$/.test(raw)) return Number(raw);
|
|
8
|
+
return raw;
|
|
9
|
+
}
|
|
10
|
+
function walkCliArgs(args, setArgValue) {
|
|
11
|
+
for(let i = 0; i < args.length; i++){
|
|
12
|
+
const arg = args[i];
|
|
13
|
+
if (!arg.startsWith('--')) continue;
|
|
14
|
+
const body = arg.slice(2);
|
|
15
|
+
const eqIdx = body.indexOf('=');
|
|
16
|
+
if (eqIdx >= 0) setArgValue(body.slice(0, eqIdx), parseValue(body.slice(eqIdx + 1)));
|
|
17
|
+
else if (args[i + 1] && !args[i + 1].startsWith('--')) {
|
|
18
|
+
i++;
|
|
19
|
+
setArgValue(body, parseValue(args[i]));
|
|
20
|
+
} else setArgValue(body, true);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function parseCliArgs(args) {
|
|
24
|
+
const result = {};
|
|
25
|
+
walkCliArgs(args, (key, value)=>{
|
|
26
|
+
result[key] = value;
|
|
27
|
+
});
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
function formatCliOptionName(name) {
|
|
31
|
+
return `--${name}`;
|
|
32
|
+
}
|
|
33
|
+
function getCliOptionDisplay(key, cliOption) {
|
|
34
|
+
const label = formatCliOptionName(cliOption?.preferredName ?? key);
|
|
35
|
+
const aliases = [
|
|
36
|
+
...new Set(cliOption?.aliases ?? [])
|
|
37
|
+
].map((alias)=>formatCliOptionName(alias)).filter((alias)=>alias !== label);
|
|
38
|
+
return {
|
|
39
|
+
label,
|
|
40
|
+
aliases
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function getAcceptedCliOptionNames(key, cliOption) {
|
|
44
|
+
return [
|
|
45
|
+
...new Set(cliOption ? [
|
|
46
|
+
cliOption.preferredName ?? key,
|
|
47
|
+
...cliOption.aliases ?? []
|
|
48
|
+
] : [
|
|
49
|
+
key,
|
|
50
|
+
...getKeyAliases(key)
|
|
51
|
+
])
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
function toOptionalCliSchemaField(field) {
|
|
55
|
+
if ('object' == typeof field && null !== field && 'function' == typeof field.optional) return field.optional();
|
|
56
|
+
const description = 'object' == typeof field && null !== field && "description" in field && 'string' == typeof field.description ? field.description : void 0;
|
|
57
|
+
return description ? z.any().describe(description) : z.any();
|
|
58
|
+
}
|
|
59
|
+
function buildCliArgSchema(def) {
|
|
60
|
+
return Object.fromEntries(Object.entries(def.schema).flatMap(([key, zodType])=>getAcceptedCliOptionNames(key, def.cli?.options?.[key]).map((cliKey)=>[
|
|
61
|
+
cliKey,
|
|
62
|
+
toOptionalCliSchemaField(zodType)
|
|
63
|
+
])));
|
|
64
|
+
}
|
|
65
|
+
function buildDisallowedCliSpellings(def) {
|
|
66
|
+
const disallowedSpellings = new Set();
|
|
67
|
+
for (const [key] of Object.entries(def.schema)){
|
|
68
|
+
const cliOption = def.cli?.options?.[key];
|
|
69
|
+
const acceptedNames = new Set(getAcceptedCliOptionNames(key, cliOption));
|
|
70
|
+
const knownSpellings = new Set([
|
|
71
|
+
key,
|
|
72
|
+
...getKeyAliases(key),
|
|
73
|
+
...cliOption?.preferredName ? getKeyAliases(cliOption.preferredName) : [],
|
|
74
|
+
...cliOption?.aliases ?? []
|
|
75
|
+
]);
|
|
76
|
+
for (const spelling of knownSpellings)if (!acceptedNames.has(spelling)) disallowedSpellings.add(spelling);
|
|
77
|
+
}
|
|
78
|
+
return disallowedSpellings;
|
|
79
|
+
}
|
|
80
|
+
function formatCliValidationError(scriptName, commandName, def, rawArgs) {
|
|
81
|
+
if (0 === Object.keys(def.schema).length) return;
|
|
82
|
+
const cliSchema = z.object(buildCliArgSchema(def)).strict();
|
|
83
|
+
const parsed = cliSchema.safeParse(rawArgs);
|
|
84
|
+
if (parsed.success) return;
|
|
85
|
+
const disallowedSpellings = buildDisallowedCliSpellings(def);
|
|
86
|
+
const unknownKeys = parsed.error.issues.flatMap((issue)=>'unrecognized_keys' === issue.code ? issue.keys : []);
|
|
87
|
+
if (unknownKeys.length > 0) return unknownKeys.map((key)=>{
|
|
88
|
+
if (disallowedSpellings.has(key)) return `Unsupported option "--${key}" for ${scriptName} ${commandName}.`;
|
|
89
|
+
return `Unknown option "--${key}" for ${scriptName} ${commandName}.`;
|
|
90
|
+
}).join('\n');
|
|
91
|
+
const [issue] = parsed.error.issues;
|
|
92
|
+
const optionName = 'string' == typeof issue?.path[0] ? `--${issue.path[0]}` : 'CLI arguments';
|
|
93
|
+
return `Invalid value for "${optionName}" in ${scriptName} ${commandName}: ${issue?.message ?? parsed.error.message}`;
|
|
94
|
+
}
|
|
95
|
+
export { formatCliValidationError, getCliOptionDisplay, parseCliArgs, parseValue };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
function _define_property(obj, key, value) {
|
|
2
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
3
|
+
value: value,
|
|
4
|
+
enumerable: true,
|
|
5
|
+
configurable: true,
|
|
6
|
+
writable: true
|
|
7
|
+
});
|
|
8
|
+
else obj[key] = value;
|
|
9
|
+
return obj;
|
|
10
|
+
}
|
|
11
|
+
class CLIError extends Error {
|
|
12
|
+
constructor(message, exitCode = 1){
|
|
13
|
+
super(message), _define_property(this, "exitCode", void 0), this.exitCode = exitCode;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function reportCLIError(error, log = console.error) {
|
|
17
|
+
if (error instanceof CLIError) {
|
|
18
|
+
log(error.message);
|
|
19
|
+
return error.exitCode;
|
|
20
|
+
}
|
|
21
|
+
log(error);
|
|
22
|
+
return 1;
|
|
23
|
+
}
|
|
24
|
+
export { CLIError, reportCLIError };
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { existsSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import dotenv from "dotenv";
|
|
5
|
+
import { getDebug } from "../logger.mjs";
|
|
6
|
+
import { formatCliValidationError, getCliOptionDisplay, parseCliArgs, parseValue } from "./cli-args.mjs";
|
|
7
|
+
import { CLIError, reportCLIError } from "./cli-error.mjs";
|
|
8
|
+
const debug = getDebug('cli-runner');
|
|
9
|
+
function outputContentItem(item, isError) {
|
|
10
|
+
switch(item.type){
|
|
11
|
+
case 'text':
|
|
12
|
+
if (isError) console.error(item.text);
|
|
13
|
+
else console.log(item.text);
|
|
14
|
+
break;
|
|
15
|
+
case 'image':
|
|
16
|
+
{
|
|
17
|
+
const filename = `screenshot-${Date.now()}.png`;
|
|
18
|
+
const filepath = join(tmpdir(), filename);
|
|
19
|
+
writeFileSync(filepath, Buffer.from(item.data, 'base64'));
|
|
20
|
+
console.log(`Screenshot saved: ${filepath}`);
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
default:
|
|
24
|
+
console.log(`[${item.type} content not displayed in CLI]`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function outputResult(result) {
|
|
28
|
+
for (const item of result.content)outputContentItem(item, result.isError ?? false);
|
|
29
|
+
}
|
|
30
|
+
function removePrefix(name, prefix) {
|
|
31
|
+
if (prefix && name.startsWith(prefix)) return name.slice(prefix.length);
|
|
32
|
+
return name;
|
|
33
|
+
}
|
|
34
|
+
function printCommandHelp(scriptName, cmd) {
|
|
35
|
+
const { def } = cmd;
|
|
36
|
+
console.log(`\nUsage: ${scriptName} ${cmd.name} [options]\n`);
|
|
37
|
+
console.log(def.description);
|
|
38
|
+
const schemaEntries = Object.entries(def.schema);
|
|
39
|
+
if (schemaEntries.length > 0) {
|
|
40
|
+
const optionWidth = Math.max(22, ...schemaEntries.map(([key])=>getCliOptionDisplay(key, def.cli?.options?.[key]).label.length));
|
|
41
|
+
console.log('\nOptions:');
|
|
42
|
+
for (const [key, zodType] of schemaEntries){
|
|
43
|
+
const { label, aliases } = getCliOptionDisplay(key, def.cli?.options?.[key]);
|
|
44
|
+
const desc = zodType.description ?? '';
|
|
45
|
+
const aliasText = aliases.length > 0 ? ` (aliases: ${aliases.join(', ')})` : '';
|
|
46
|
+
console.log(` ${label.padEnd(optionWidth)} ${desc}${aliasText}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function printVersion(scriptName, version) {
|
|
51
|
+
console.log(`${scriptName} v${version}`);
|
|
52
|
+
}
|
|
53
|
+
function printHelp(scriptName, commands, version) {
|
|
54
|
+
if (version) {
|
|
55
|
+
printVersion(scriptName, version);
|
|
56
|
+
console.log('');
|
|
57
|
+
}
|
|
58
|
+
console.log(`\nUsage: ${scriptName} <command> [options]\n`);
|
|
59
|
+
console.log('Commands:');
|
|
60
|
+
for (const { name, def } of commands.filter((command)=>!command.hidden))console.log(` ${name.padEnd(30)} ${def.description}`);
|
|
61
|
+
console.log(` ${'version'.padEnd(30)} Show CLI version`);
|
|
62
|
+
console.log(`\nRun "${scriptName} <command> --help" for more info.`);
|
|
63
|
+
}
|
|
64
|
+
async function runToolsCLI(tools, scriptName, options) {
|
|
65
|
+
const rawArgs = options?.argv ?? process.argv.slice(2);
|
|
66
|
+
debug('CLI invoked: %s %s', scriptName, rawArgs.join(' '));
|
|
67
|
+
const envFile = join(process.cwd(), '.env');
|
|
68
|
+
if (existsSync(envFile)) dotenv.config({
|
|
69
|
+
path: envFile
|
|
70
|
+
});
|
|
71
|
+
await tools.initTools();
|
|
72
|
+
const commands = tools.getToolDefinitions().map((def)=>({
|
|
73
|
+
name: removePrefix(def.name, options?.stripPrefix).toLowerCase(),
|
|
74
|
+
def
|
|
75
|
+
}));
|
|
76
|
+
if (options?.extraCommands?.length) commands.push(...options.extraCommands.flatMap((cmd)=>[
|
|
77
|
+
{
|
|
78
|
+
name: cmd.name.toLowerCase(),
|
|
79
|
+
def: cmd.def,
|
|
80
|
+
hidden: cmd.hidden
|
|
81
|
+
},
|
|
82
|
+
...(cmd.aliases ?? []).map((alias)=>({
|
|
83
|
+
name: alias.toLowerCase(),
|
|
84
|
+
def: cmd.def,
|
|
85
|
+
hidden: true
|
|
86
|
+
}))
|
|
87
|
+
]));
|
|
88
|
+
const cliVersion = options?.version;
|
|
89
|
+
const [commandName, ...restArgs] = rawArgs;
|
|
90
|
+
if (!commandName || '--help' === commandName || '-h' === commandName) {
|
|
91
|
+
debug('showing help (no command or --help flag)');
|
|
92
|
+
printHelp(scriptName, commands, cliVersion);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if ('--version' === commandName || '-v' === commandName || 'version' === commandName.toLowerCase()) {
|
|
96
|
+
if (!cliVersion) throw new CLIError('Failed to determine CLI version');
|
|
97
|
+
printVersion(scriptName, cliVersion);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const match = commands.find((c)=>c.name.toLowerCase() === commandName.toLowerCase());
|
|
101
|
+
if (!match) {
|
|
102
|
+
debug('unknown command: %s', commandName);
|
|
103
|
+
console.error(`Unknown command: ${commandName}`);
|
|
104
|
+
printHelp(scriptName, commands, cliVersion);
|
|
105
|
+
throw new CLIError(`Unknown command: ${commandName}`);
|
|
106
|
+
}
|
|
107
|
+
const parsedArgs = parseCliArgs(restArgs);
|
|
108
|
+
if (true === parsedArgs.help) {
|
|
109
|
+
debug('showing command help for: %s', match.name);
|
|
110
|
+
printCommandHelp(scriptName, match);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const cliValidationError = formatCliValidationError(scriptName, match.name, match.def, parsedArgs);
|
|
114
|
+
if (cliValidationError) throw new CLIError(cliValidationError);
|
|
115
|
+
debug('command: %s, args: %s', match.name, JSON.stringify(parsedArgs));
|
|
116
|
+
const result = await match.def.handler(parsedArgs);
|
|
117
|
+
debug('command %s completed, isError: %s', match.name, result.isError ?? false);
|
|
118
|
+
outputResult(result);
|
|
119
|
+
await tools.destroy();
|
|
120
|
+
if (result.isError) throw new CLIError('Command failed', 1);
|
|
121
|
+
}
|
|
122
|
+
export { CLIError, parseCliArgs, parseValue, removePrefix, reportCLIError, runToolsCLI };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { CLIError, reportCLIError } from "./cli-error.mjs";
|
|
2
|
+
import { parseCliArgs, parseValue } from "./cli-args.mjs";
|
|
3
|
+
import { removePrefix, runToolsCLI } from "./cli-runner.mjs";
|
|
4
|
+
export { CLIError, parseCliArgs, parseValue, removePrefix, reportCLIError, runToolsCLI };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import node_path from "node:path";
|
|
4
|
+
import { getBasicEnvValue } from "./env/basic.mjs";
|
|
5
|
+
import { MIDSCENE_RUN_DIR } from "./env/types.mjs";
|
|
6
|
+
import { ifInNode } from "./utils.mjs";
|
|
7
|
+
const defaultRunDirName = 'midscene_run';
|
|
8
|
+
const getMidsceneRunDir = ()=>{
|
|
9
|
+
if (!ifInNode) return '';
|
|
10
|
+
return getBasicEnvValue(MIDSCENE_RUN_DIR) || defaultRunDirName;
|
|
11
|
+
};
|
|
12
|
+
const getMidsceneRunBaseDir = ()=>{
|
|
13
|
+
if (!ifInNode) return '';
|
|
14
|
+
let basePath = node_path.resolve(process.cwd(), getMidsceneRunDir());
|
|
15
|
+
if (!existsSync(basePath)) try {
|
|
16
|
+
mkdirSync(basePath, {
|
|
17
|
+
recursive: true
|
|
18
|
+
});
|
|
19
|
+
} catch (error) {
|
|
20
|
+
basePath = node_path.join(tmpdir(), defaultRunDirName);
|
|
21
|
+
mkdirSync(basePath, {
|
|
22
|
+
recursive: true
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return basePath;
|
|
26
|
+
};
|
|
27
|
+
const getMidsceneRunSubDir = (subdir)=>{
|
|
28
|
+
if (!ifInNode) return '';
|
|
29
|
+
const basePath = getMidsceneRunBaseDir();
|
|
30
|
+
const logPath = node_path.join(basePath, subdir);
|
|
31
|
+
if (!existsSync(logPath)) mkdirSync(logPath, {
|
|
32
|
+
recursive: true
|
|
33
|
+
});
|
|
34
|
+
return logPath;
|
|
35
|
+
};
|
|
36
|
+
const ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED = 'NOT_IMPLEMENTED_AS_DESIGNED';
|
|
37
|
+
export { ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED, defaultRunDirName, getMidsceneRunBaseDir, getMidsceneRunDir, getMidsceneRunSubDir };
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
const PLAYWRIGHT_EXAMPLE_CODE = `
|
|
2
|
+
// Reference the following code to generate Midscene test cases
|
|
3
|
+
// The following is test code for Midscene AI, for reference
|
|
4
|
+
// The following is Playwright syntax, you can use Playwright to assist in test generation
|
|
5
|
+
IMPORTANT: Follow these exact type signatures for AI functions:
|
|
6
|
+
|
|
7
|
+
// Type signatures for AI functions:
|
|
8
|
+
aiAct(prompt: string, options?: { cacheable?: boolean, deepThink?: 'unset' | true | false }): Promise<void>
|
|
9
|
+
aiInput(text: string, locate: string, options?: { deepLocate?: boolean, xpath?: string, cacheable?: boolean }): Promise<void>
|
|
10
|
+
aiTap(locate: string, options?: { deepLocate?: boolean, xpath?: string, cacheable?: boolean }): Promise<void>
|
|
11
|
+
aiHover(locate: string, options?: { deepLocate?: boolean, xpath?: string, cacheable?: boolean }): Promise<void>
|
|
12
|
+
aiDoubleClick(locate: string, options?: { deepLocate?: boolean, xpath?: string, cacheable?: boolean }): Promise<void>
|
|
13
|
+
aiKeyboardPress(key: string, locate?: string, options?: { deepLocate?: boolean, xpath?: string, cacheable?: boolean }): Promise<void>
|
|
14
|
+
aiScroll(locate: string | undefined, options: {
|
|
15
|
+
direction?: 'up' | 'down' | 'left' | 'right',
|
|
16
|
+
scrollType?: 'singleAction' | 'scrollToBottom' | 'scrollToTop' | 'scrollToRight' | 'scrollToLeft',
|
|
17
|
+
distance?: number | null,
|
|
18
|
+
deepLocate?: boolean,
|
|
19
|
+
xpath?: string,
|
|
20
|
+
cacheable?: boolean
|
|
21
|
+
}): Promise<void>
|
|
22
|
+
aiAssert(assertion: string, options?: { errorMessage?: string }): Promise<void>
|
|
23
|
+
aiWaitFor(prompt: string, options?: { timeout?: number }): Promise<void>
|
|
24
|
+
aiQuery<T>(queryObject: Record<string, string>): Promise<T> // Extracts data from page based on descriptions
|
|
25
|
+
|
|
26
|
+
// examples:
|
|
27
|
+
// Reference the following code to generate Midscene test cases
|
|
28
|
+
// The following is test code for Midscene AI, for reference
|
|
29
|
+
// The following is Playwright syntax, you can use Playwright to assist in test generation
|
|
30
|
+
import { test as base } from '@playwright/test';
|
|
31
|
+
import type { PlayWrightAiFixtureType } from '@godscene/web/playwright';
|
|
32
|
+
import { PlaywrightAiFixture } from '@godscene/web/playwright';
|
|
33
|
+
|
|
34
|
+
const test = base.extend<PlayWrightAiFixtureType>(PlaywrightAiFixture({
|
|
35
|
+
waitForNetworkIdleTimeout: 2000, // optional, the timeout for waiting for network idle between each action, default is 2000ms
|
|
36
|
+
}));
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
test.beforeEach(async ({ page }) => {
|
|
40
|
+
await page.goto('https://www.xxx.com/');
|
|
41
|
+
await page.setViewportSize({ width: 1920, height: 1080 });
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('ai shop', async ({
|
|
45
|
+
aiAct,
|
|
46
|
+
aiInput,
|
|
47
|
+
aiAssert,
|
|
48
|
+
aiQuery,
|
|
49
|
+
aiKeyboardPress,
|
|
50
|
+
aiHover,
|
|
51
|
+
aiTap,
|
|
52
|
+
aiWaitFor,
|
|
53
|
+
agentForPage,
|
|
54
|
+
page,
|
|
55
|
+
}) => {
|
|
56
|
+
// login
|
|
57
|
+
await aiAssert('The page shows the login interface');
|
|
58
|
+
await aiInput('user_name', 'in user name input');
|
|
59
|
+
await aiInput('password', 'in password input');
|
|
60
|
+
await aiKeyboardPress('Enter', 'Login Button');
|
|
61
|
+
|
|
62
|
+
// check the login success
|
|
63
|
+
await aiWaitFor('The page shows that the loading is complete');
|
|
64
|
+
await aiAssert('The current page shows the product detail page');
|
|
65
|
+
|
|
66
|
+
// check the product info
|
|
67
|
+
const dataA = await aiQuery({
|
|
68
|
+
userInfo: 'User information in the format {name: string}',
|
|
69
|
+
theFirstProductInfo: 'The first product info in the format {name: string, price: number}',
|
|
70
|
+
});
|
|
71
|
+
expect(dataA.theFirstProductInfo.name).toBe('xxx');
|
|
72
|
+
expect(dataA.theFirstProductInfo.price).toBe(100);
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
// add to cart
|
|
76
|
+
await aiTap('click add to cart button');
|
|
77
|
+
|
|
78
|
+
await aiTap('click right top cart icon');
|
|
79
|
+
await aiAssert('The cart icon shows the number 1');
|
|
80
|
+
});
|
|
81
|
+
`;
|
|
82
|
+
const YAML_EXAMPLE_CODE = `
|
|
83
|
+
CRITICAL - YAML Indentation Rules:
|
|
84
|
+
For actions with additional parameters (aiScroll, aiInput, aiKeyboardPress), the parameters must be SIBLING keys at the SAME indentation level as the action key, NOT nested children indented further.
|
|
85
|
+
CORRECT (parameters align with the action key):
|
|
86
|
+
- aiScroll:
|
|
87
|
+
direction: 'down'
|
|
88
|
+
scrollType: 'singleAction'
|
|
89
|
+
distance: 500
|
|
90
|
+
locate: "main content area"
|
|
91
|
+
- aiInput: 'text value'
|
|
92
|
+
locate: 'input field description'
|
|
93
|
+
WRONG (parameters are indented further than the action key, DO NOT do this):
|
|
94
|
+
- aiScroll:
|
|
95
|
+
direction: 'down'
|
|
96
|
+
scrollType: 'singleAction'
|
|
97
|
+
- aiInput: 'text value'
|
|
98
|
+
locate: 'input field description'
|
|
99
|
+
|
|
100
|
+
1. Format:
|
|
101
|
+
|
|
102
|
+
web:
|
|
103
|
+
url: "starting_url"
|
|
104
|
+
viewportWidth: 1280
|
|
105
|
+
viewportHeight: 960
|
|
106
|
+
|
|
107
|
+
tasks:
|
|
108
|
+
- name: "descriptive task name"
|
|
109
|
+
flow:
|
|
110
|
+
- aiTap: "element description"
|
|
111
|
+
xpath: '/html/body/div[1]/button[1]'
|
|
112
|
+
- aiInput: 'text value'
|
|
113
|
+
locate: 'input field description'
|
|
114
|
+
xpath: '/html/body/div[1]/input[1]'
|
|
115
|
+
- aiScroll:
|
|
116
|
+
direction: 'down'
|
|
117
|
+
scrollType: 'singleAction'
|
|
118
|
+
distance: 500
|
|
119
|
+
locate: "scrollable area description"
|
|
120
|
+
xpath: '/html/body/div[1]/main[1]'
|
|
121
|
+
- aiAssert: "expected state"
|
|
122
|
+
- sleep: 1000
|
|
123
|
+
|
|
124
|
+
2. Action Types:
|
|
125
|
+
- aiTap: for clicks (natural language targeting)
|
|
126
|
+
- aiInput: for text input with 'locate' field
|
|
127
|
+
- aiScroll: with direction and scrollType
|
|
128
|
+
- aiAssert: for validations
|
|
129
|
+
- sleep: for delays (milliseconds)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
YAML type
|
|
134
|
+
tasks:
|
|
135
|
+
- name: <name>
|
|
136
|
+
continueOnError: <boolean> # Optional, whether to continue to the next task on error, defaults to false.
|
|
137
|
+
flow:
|
|
138
|
+
# Auto Planning (.ai)
|
|
139
|
+
# ----------------
|
|
140
|
+
|
|
141
|
+
# Perform an interaction. \`ai\` is a shorthand for \`aiAct\`.
|
|
142
|
+
- ai: <prompt>
|
|
143
|
+
cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.
|
|
144
|
+
|
|
145
|
+
# This usage is the same as \`ai\`.
|
|
146
|
+
- aiAct: <prompt>
|
|
147
|
+
cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.
|
|
148
|
+
|
|
149
|
+
# Instant Action (.aiTap, .aiDoubleClick, .aiHover, .aiInput, .aiKeyboardPress, .aiScroll)
|
|
150
|
+
# ----------------
|
|
151
|
+
|
|
152
|
+
# Tap an element described by a prompt.
|
|
153
|
+
- aiTap: <prompt>
|
|
154
|
+
deepLocate: <boolean> # Optional, whether to use deepLocate to precisely locate the element. Defaults to False.
|
|
155
|
+
xpath: <xpath> # Optional, the xpath of the target element for the operation. If provided, Midscene will prioritize this xpath to find the element before using the cache and the AI model. Defaults to empty.
|
|
156
|
+
cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.
|
|
157
|
+
|
|
158
|
+
# Double click an element described by a prompt.
|
|
159
|
+
- aiDoubleClick: <prompt>
|
|
160
|
+
deepLocate: <boolean> # Optional, whether to use deepLocate to precisely locate the element. Defaults to False.
|
|
161
|
+
xpath: <xpath> # Optional, the xpath of the target element for the operation. If provided, Midscene will prioritize this xpath to find the element before using the cache and the AI model. Defaults to empty.
|
|
162
|
+
cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.
|
|
163
|
+
|
|
164
|
+
# Hover over an element described by a prompt.
|
|
165
|
+
- aiHover: <prompt>
|
|
166
|
+
deepLocate: <boolean> # Optional, whether to use deepLocate to precisely locate the element. Defaults to False.
|
|
167
|
+
xpath: <xpath> # Optional, the xpath of the target element for the operation. If provided, Midscene will prioritize this xpath to find the element before using the cache and the AI model. Defaults to empty.
|
|
168
|
+
cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.
|
|
169
|
+
|
|
170
|
+
# Input text into an element described by a prompt.
|
|
171
|
+
- aiInput: <final text content of the input>
|
|
172
|
+
locate: <prompt>
|
|
173
|
+
deepLocate: <boolean> # Optional, whether to use deepLocate to precisely locate the element. Defaults to False.
|
|
174
|
+
xpath: <xpath> # Optional, the xpath of the target element for the operation. If provided, Midscene will prioritize this xpath to find the element before using the cache and the AI model. Defaults to empty.
|
|
175
|
+
cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.
|
|
176
|
+
|
|
177
|
+
# Press a key (e.g., Enter, Tab, Escape) on an element described by a prompt.
|
|
178
|
+
- aiKeyboardPress: <key>
|
|
179
|
+
locate: <prompt>
|
|
180
|
+
deepLocate: <boolean> # Optional, whether to use deepLocate to precisely locate the element. Defaults to False.
|
|
181
|
+
xpath: <xpath> # Optional, the xpath of the target element for the operation. If provided, Midscene will prioritize this xpath to find the element before using the cache and the AI model. Defaults to empty.
|
|
182
|
+
cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.
|
|
183
|
+
|
|
184
|
+
# Scroll globally or on an element described by a prompt.
|
|
185
|
+
- aiScroll:
|
|
186
|
+
direction: 'up' # or 'down' | 'left' | 'right'
|
|
187
|
+
scrollType: 'singleAction' # or 'scrollToTop' | 'scrollToBottom' | 'scrollToLeft' | 'scrollToRight'
|
|
188
|
+
distance: <number> # Optional, the scroll distance in pixels.
|
|
189
|
+
locate: <prompt> # Optional, the element to scroll on.
|
|
190
|
+
deepLocate: <boolean> # Optional, whether to use deepLocate to precisely locate the element. Defaults to False.
|
|
191
|
+
xpath: <xpath> # Optional, the xpath of the target element for the operation. If provided, Midscene will prioritize this xpath to find the element before using the cache and the AI model. Defaults to empty.
|
|
192
|
+
cacheable: <boolean> # Optional, whether to cache the result of this API call when the [caching feature](./caching.mdx) is enabled. Defaults to True.
|
|
193
|
+
|
|
194
|
+
# Record the current screenshot with a description in the report file.
|
|
195
|
+
- recordToReport: <title> # Optional, the title of the screenshot. If not provided, the title will be 'untitled'.
|
|
196
|
+
content: <content> # Optional, the description of the screenshot.
|
|
197
|
+
|
|
198
|
+
# Data Extraction
|
|
199
|
+
# ----------------
|
|
200
|
+
|
|
201
|
+
# Perform a query that returns a JSON object.
|
|
202
|
+
- aiQuery: <prompt> # Remember to describe the format of the result in the prompt.
|
|
203
|
+
name: <name> # The key for the query result in the JSON output.
|
|
204
|
+
|
|
205
|
+
# More APIs
|
|
206
|
+
# ----------------
|
|
207
|
+
|
|
208
|
+
# Wait for a condition to be met, with a timeout (in ms, optional, defaults to 30000).
|
|
209
|
+
- aiWaitFor: <prompt>
|
|
210
|
+
timeout: <ms>
|
|
211
|
+
|
|
212
|
+
# Perform an assertion.
|
|
213
|
+
- aiAssert: <prompt>
|
|
214
|
+
errorMessage: <error-message> # Optional, the error message to print if the assertion fails.
|
|
215
|
+
|
|
216
|
+
# Wait for a specified amount of time.
|
|
217
|
+
- sleep: <ms>
|
|
218
|
+
|
|
219
|
+
# Execute a piece of JavaScript code in the web page context.
|
|
220
|
+
- javascript: <javascript>
|
|
221
|
+
name: <name> # Optional, assign a name to the return value, which will be used as a key in the JSON output.
|
|
222
|
+
|
|
223
|
+
- name: <name>
|
|
224
|
+
flow:
|
|
225
|
+
# ...
|
|
226
|
+
`;
|
|
227
|
+
export { PLAYWRIGHT_EXAMPLE_CODE, YAML_EXAMPLE_CODE };
|