testdriverai 5.7.43 → 5.7.44
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/agent.js +44 -44
- package/index.js +0 -2
- package/lib/commander.js +199 -203
- package/lib/commands.js +63 -35
- package/lib/config.js +1 -3
- package/lib/events.js +1 -1
- package/lib/focus-application.js +14 -8
- package/lib/generator.js +3 -4
- package/lib/init.js +10 -10
- package/lib/logger.js +226 -5
- package/lib/network.js +0 -3
- package/lib/outputs.js +1 -1
- package/lib/parser.js +22 -23
- package/lib/redraw.js +47 -27
- package/lib/resources/prerun.yaml +2 -2
- package/lib/sandbox.js +20 -20
- package/lib/sdk.js +4 -4
- package/lib/session.js +0 -2
- package/lib/system.js +1 -1
- package/lib/theme.js +13 -0
- package/lib/upload-secrets.js +1 -1
- package/package.json +1 -1
- package/testdriver/type-repeated.yaml +21 -0
package/lib/commander.js
CHANGED
|
@@ -11,16 +11,16 @@ const sdk = require("./sdk");
|
|
|
11
11
|
const outputs = require("./outputs");
|
|
12
12
|
const server = require("./ipc");
|
|
13
13
|
|
|
14
|
-
// replace all occurances of ${OUTPUT.ls} with outputs.get("ls") in every possible property of the `object`
|
|
14
|
+
// replace all occurances of ${OUTPUT.ls} with outputs.get("ls") in every possible property of the `object`
|
|
15
15
|
// this is a recursive function that will go through all the properties of the object
|
|
16
16
|
const replaceOutputs = (obj) => {
|
|
17
|
-
|
|
18
17
|
for (let key in obj) {
|
|
19
|
-
|
|
20
18
|
if (typeof obj[key] === "object") {
|
|
21
19
|
replaceOutputs(obj[key]);
|
|
22
20
|
} else if (typeof obj[key] === "string") {
|
|
23
|
-
obj[key] = obj[key].replace(/\${OUTPUT\.(.*?)}/g, (_, match) =>
|
|
21
|
+
obj[key] = obj[key].replace(/\${OUTPUT\.(.*?)}/g, (_, match) =>
|
|
22
|
+
outputs.get(match),
|
|
23
|
+
);
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
};
|
|
@@ -28,17 +28,15 @@ const replaceOutputs = (obj) => {
|
|
|
28
28
|
// object is a json representation of the individual yml command
|
|
29
29
|
// the process turns markdown -> yml -> json -> js function execution
|
|
30
30
|
const run = async (object, depth) => {
|
|
31
|
+
try {
|
|
32
|
+
logger.debug("%j", { object, depth });
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
// success returns null
|
|
35
|
+
// if this is set, it means that we need to take more action and a new thread is spawned
|
|
36
|
+
let response = null;
|
|
35
37
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
let response = null;
|
|
39
|
-
|
|
40
|
-
if (!object?.command) {
|
|
41
|
-
throw `YML is formatted improperly.
|
|
38
|
+
if (!object?.command) {
|
|
39
|
+
throw `YML is formatted improperly.
|
|
42
40
|
|
|
43
41
|
The input YML is:
|
|
44
42
|
${yaml.dump(object)}
|
|
@@ -55,206 +53,204 @@ commands:
|
|
|
55
53
|
- command: press-keys
|
|
56
54
|
keys: [command, space]
|
|
57
55
|
\`\`\``;
|
|
58
|
-
|
|
56
|
+
} else {
|
|
57
|
+
replaceOutputs(object);
|
|
59
58
|
|
|
60
|
-
|
|
59
|
+
let copy = JSON.parse(JSON.stringify(object));
|
|
61
60
|
|
|
62
|
-
|
|
61
|
+
marky.mark(object.command);
|
|
63
62
|
|
|
64
|
-
|
|
63
|
+
// we speak, log, and take images here because we want to be careful not to render a notification containing the text we're looking for
|
|
64
|
+
// or to cover the screen of some item we might want
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
// this will actually interpret the command and execute it
|
|
67
|
+
switch (object.command) {
|
|
68
|
+
case "type":
|
|
69
|
+
speak(`typing ${object.text}`);
|
|
70
|
+
server.broadcast("status", `typing ${object.text}`);
|
|
71
|
+
logger.info(generator.jsonToManual(object));
|
|
72
|
+
notify(generator.jsonToManual(object, false));
|
|
73
|
+
response = await commands.type(object.text, object.delay);
|
|
74
|
+
break;
|
|
75
|
+
case "press-keys":
|
|
76
|
+
speak(`pressing keys ${object.keys.join(",")}`);
|
|
77
|
+
server.broadcast("status", `pressing keys ${object.keys.join(",")}`);
|
|
78
|
+
logger.info(generator.jsonToManual(object));
|
|
79
|
+
notify(generator.jsonToManual(object, false));
|
|
80
|
+
response = await commands["press-keys"](object.keys);
|
|
81
|
+
break;
|
|
82
|
+
case "scroll":
|
|
83
|
+
speak(`scrolling ${object.direction}`);
|
|
84
|
+
server.broadcast("status", `scrolling ${object.direction}`);
|
|
85
|
+
logger.info(generator.jsonToManual(object));
|
|
86
|
+
notify(generator.jsonToManual(object, false));
|
|
87
|
+
response = await commands.scroll(
|
|
88
|
+
object.direction,
|
|
89
|
+
object.amount,
|
|
90
|
+
object.method,
|
|
91
|
+
);
|
|
92
|
+
break;
|
|
93
|
+
case "wait":
|
|
94
|
+
speak(`waiting ${object.timeout} seconds`);
|
|
95
|
+
server.broadcast("status", `waiting ${object.timeout} seconds`);
|
|
96
|
+
logger.info(generator.jsonToManual(object));
|
|
97
|
+
notify(generator.jsonToManual(object, false));
|
|
98
|
+
response = await commands.wait(object.timeout);
|
|
99
|
+
break;
|
|
100
|
+
case "click":
|
|
101
|
+
speak(`${object.action}`);
|
|
102
|
+
server.broadcast("status", `${object.action}`);
|
|
103
|
+
logger.info(generator.jsonToManual(object));
|
|
104
|
+
notify(generator.jsonToManual(object, false));
|
|
105
|
+
response = await commands["click"](object.x, object.y, object.action);
|
|
106
|
+
break;
|
|
107
|
+
case "hover":
|
|
108
|
+
speak(`moving mouse`);
|
|
109
|
+
server.broadcast("status", `moving mouse`);
|
|
110
|
+
logger.info(generator.jsonToManual(object));
|
|
111
|
+
notify(generator.jsonToManual(object, false));
|
|
112
|
+
response = await commands["hover"](object.x, object.y);
|
|
113
|
+
break;
|
|
114
|
+
case "drag":
|
|
115
|
+
speak(`dragging mouse`);
|
|
116
|
+
logger.info(generator.jsonToManual(object));
|
|
117
|
+
notify(generator.jsonToManual(object, false));
|
|
118
|
+
response = await commands["drag"](object.x, object.y);
|
|
119
|
+
break;
|
|
120
|
+
case "hover-text":
|
|
121
|
+
speak(`searching for ${object.description}`);
|
|
122
|
+
server.broadcast("status", `searching for ${object.description}`);
|
|
123
|
+
logger.info(generator.jsonToManual(object));
|
|
124
|
+
notify(generator.jsonToManual(object, false));
|
|
125
|
+
response = await commands["hover-text"](
|
|
126
|
+
object.text,
|
|
127
|
+
object.description,
|
|
128
|
+
object.action,
|
|
129
|
+
object.method,
|
|
130
|
+
);
|
|
131
|
+
break;
|
|
132
|
+
case "hover-image":
|
|
133
|
+
speak(`searching for image of ${object.description}`);
|
|
134
|
+
server.broadcast(
|
|
135
|
+
"status",
|
|
136
|
+
`searching for image of ${object.description}`,
|
|
137
|
+
);
|
|
138
|
+
logger.info(generator.jsonToManual(object));
|
|
139
|
+
response = await commands["hover-image"](
|
|
140
|
+
object.description,
|
|
141
|
+
object.action,
|
|
142
|
+
);
|
|
143
|
+
break;
|
|
144
|
+
case "match-image":
|
|
145
|
+
logger.info(generator.jsonToManual(object));
|
|
146
|
+
server.broadcast("status", `${object.action} image ${object.path}`);
|
|
147
|
+
notify(generator.jsonToManual(object, false));
|
|
148
|
+
response = await commands["match-image"](object.path, object.action);
|
|
149
|
+
break;
|
|
150
|
+
case "wait-for-image":
|
|
151
|
+
speak(`waiting for ${object.description}`);
|
|
152
|
+
server.broadcast("status", `waiting for ${object.description}`);
|
|
153
|
+
logger.info(generator.jsonToManual(object));
|
|
154
|
+
notify(generator.jsonToManual(object, false));
|
|
155
|
+
response = await commands["wait-for-image"](
|
|
156
|
+
object.description,
|
|
157
|
+
object.timeout,
|
|
158
|
+
);
|
|
159
|
+
break;
|
|
160
|
+
case "wait-for-text":
|
|
161
|
+
speak(`waiting for ${object.text}`);
|
|
162
|
+
server.broadcast("status", `waiting for ${object.text}`);
|
|
163
|
+
logger.info(generator.jsonToManual(object));
|
|
164
|
+
copy.text = "*****";
|
|
165
|
+
notify(generator.jsonToManual(copy, false));
|
|
166
|
+
response = await commands["wait-for-text"](
|
|
167
|
+
object.text,
|
|
168
|
+
object.timeout,
|
|
169
|
+
object.method,
|
|
170
|
+
);
|
|
171
|
+
break;
|
|
172
|
+
case "scroll-until-text":
|
|
173
|
+
speak(`scrolling until ${object.text}`);
|
|
174
|
+
server.broadcast("status", `scrolling until ${object.text}`);
|
|
175
|
+
logger.info(generator.jsonToManual(object));
|
|
176
|
+
copy.text = "*****";
|
|
177
|
+
notify(generator.jsonToManual(copy, false));
|
|
178
|
+
response = await commands["scroll-until-text"](
|
|
179
|
+
object.text,
|
|
180
|
+
object.direction,
|
|
181
|
+
object.distance,
|
|
182
|
+
object.textMatchMethod,
|
|
183
|
+
object.method,
|
|
184
|
+
);
|
|
185
|
+
break;
|
|
186
|
+
case "scroll-until-image":
|
|
187
|
+
speak(`scrolling until ${object.description}`);
|
|
188
|
+
server.broadcast("status", `scrolling until ${object.description}`);
|
|
189
|
+
logger.info(generator.jsonToManual(object));
|
|
190
|
+
notify(generator.jsonToManual(object, false));
|
|
191
|
+
response = await commands["scroll-until-image"](
|
|
192
|
+
object.description,
|
|
193
|
+
object.direction,
|
|
194
|
+
object.distance,
|
|
195
|
+
object.method,
|
|
196
|
+
);
|
|
197
|
+
break;
|
|
198
|
+
case "focus-application":
|
|
199
|
+
speak(`focusing ${object.name}`);
|
|
200
|
+
server.broadcast("status", `focusing ${object.name}`);
|
|
201
|
+
logger.info(generator.jsonToManual(object));
|
|
202
|
+
notify(generator.jsonToManual(object, false));
|
|
203
|
+
response = await commands["focus-application"](object.name);
|
|
204
|
+
break;
|
|
205
|
+
case "remember": {
|
|
206
|
+
logger.info(generator.jsonToManual(object));
|
|
207
|
+
notify(generator.jsonToManual(object, false));
|
|
208
|
+
let value = await commands["remember"](object.description);
|
|
209
|
+
console.log(value);
|
|
210
|
+
outputs.set(object.output, value);
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
case "assert":
|
|
214
|
+
speak(`asserting ${object.expect}`);
|
|
215
|
+
server.broadcast("status", `asserting ${object.expect}`);
|
|
216
|
+
logger.info(generator.jsonToManual(object));
|
|
217
|
+
notify(generator.jsonToManual(object, false));
|
|
218
|
+
response = await commands.assert(object.expect, object.async);
|
|
219
|
+
break;
|
|
220
|
+
case "exec":
|
|
221
|
+
speak(`exec`);
|
|
222
|
+
server.broadcast("status", `exec`);
|
|
223
|
+
logger.info(generator.jsonToManual(object));
|
|
224
|
+
notify(generator.jsonToManual(object, false));
|
|
67
225
|
|
|
68
|
-
|
|
69
|
-
|
|
226
|
+
response = await commands.exec(
|
|
227
|
+
object.lang,
|
|
228
|
+
object.mac,
|
|
229
|
+
object.windows,
|
|
230
|
+
object.linux,
|
|
231
|
+
object.silent,
|
|
232
|
+
);
|
|
70
233
|
|
|
71
|
-
|
|
72
|
-
switch (object.command) {
|
|
73
|
-
case "type":
|
|
74
|
-
speak(`typing ${object.text}`);
|
|
75
|
-
server.broadcast("status", `typing ${object.text}`);
|
|
76
|
-
logger.info(generator.jsonToManual(object));
|
|
77
|
-
notify(generator.jsonToManual(object, false));
|
|
78
|
-
response = await commands.type(object.text, object.delay);
|
|
79
|
-
break;
|
|
80
|
-
case "press-keys":
|
|
81
|
-
speak(`pressing keys ${object.keys.join(",")}`);
|
|
82
|
-
server.broadcast("status", `pressing keys ${object.keys.join(",")}`);
|
|
83
|
-
logger.info(generator.jsonToManual(object));
|
|
84
|
-
notify(generator.jsonToManual(object, false));
|
|
85
|
-
response = await commands["press-keys"](object.keys);
|
|
86
|
-
break;
|
|
87
|
-
case "scroll":
|
|
88
|
-
speak(`scrolling ${object.direction}`);
|
|
89
|
-
server.broadcast("status", `scrolling ${object.direction}`);
|
|
90
|
-
logger.info(generator.jsonToManual(object));
|
|
91
|
-
notify(generator.jsonToManual(object, false));
|
|
92
|
-
response = await commands.scroll(
|
|
93
|
-
object.direction,
|
|
94
|
-
object.amount,
|
|
95
|
-
object.method,
|
|
96
|
-
);
|
|
97
|
-
break;
|
|
98
|
-
case "wait":
|
|
99
|
-
speak(`waiting ${object.timeout} seconds`);
|
|
100
|
-
server.broadcast("status", `waiting ${object.timeout} seconds`);
|
|
101
|
-
logger.info(generator.jsonToManual(object));
|
|
102
|
-
notify(generator.jsonToManual(object, false));
|
|
103
|
-
response = await commands.wait(object.timeout);
|
|
104
|
-
break;
|
|
105
|
-
case "click":
|
|
106
|
-
speak(`${object.action}`);
|
|
107
|
-
server.broadcast("status", `${object.action}`);
|
|
108
|
-
logger.info(generator.jsonToManual(object));
|
|
109
|
-
notify(generator.jsonToManual(object, false));
|
|
110
|
-
response = await commands["click"](
|
|
111
|
-
object.x,
|
|
112
|
-
object.y,
|
|
113
|
-
object.action,
|
|
114
|
-
);
|
|
115
|
-
break;
|
|
116
|
-
case "hover":
|
|
117
|
-
speak(`moving mouse`);
|
|
118
|
-
server.broadcast("status", `moving mouse`);
|
|
119
|
-
logger.info(generator.jsonToManual(object));
|
|
120
|
-
notify(generator.jsonToManual(object, false));
|
|
121
|
-
response = await commands["hover"](object.x, object.y);
|
|
122
|
-
break;
|
|
123
|
-
case "drag":
|
|
124
|
-
speak(`dragging mouse`);
|
|
125
|
-
logger.info(generator.jsonToManual(object));
|
|
126
|
-
notify(generator.jsonToManual(object, false));
|
|
127
|
-
response = await commands["drag"](object.x, object.y);
|
|
128
|
-
break;
|
|
129
|
-
case "hover-text":
|
|
130
|
-
speak(`searching for ${object.description}`);
|
|
131
|
-
server.broadcast("status", `searching for ${object.description}`);
|
|
132
|
-
logger.info(generator.jsonToManual(object));
|
|
133
|
-
notify(generator.jsonToManual(object, false));
|
|
134
|
-
response = await commands["hover-text"](
|
|
135
|
-
object.text,
|
|
136
|
-
object.description,
|
|
137
|
-
object.action,
|
|
138
|
-
object.method,
|
|
139
|
-
);
|
|
140
|
-
break;
|
|
141
|
-
case "hover-image":
|
|
142
|
-
speak(`searching for image of ${object.description}`);
|
|
143
|
-
server.broadcast("status", `searching for image of ${object.description}`);
|
|
144
|
-
logger.info(generator.jsonToManual(object));
|
|
145
|
-
response = await commands["hover-image"](
|
|
146
|
-
object.description,
|
|
147
|
-
object.action,
|
|
148
|
-
);
|
|
149
|
-
break;
|
|
150
|
-
case "match-image":
|
|
151
|
-
logger.info(generator.jsonToManual(object));
|
|
152
|
-
server.broadcast("status", `${object.action} image ${object.path}`);
|
|
153
|
-
notify(generator.jsonToManual(object, false));
|
|
154
|
-
response = await commands["match-image"](
|
|
155
|
-
object.path,
|
|
156
|
-
object.action
|
|
157
|
-
);
|
|
158
|
-
break;
|
|
159
|
-
case "wait-for-image":
|
|
160
|
-
speak(`waiting for ${object.description}`);
|
|
161
|
-
server.broadcast("status", `waiting for ${object.description}`);
|
|
162
|
-
logger.info(generator.jsonToManual(object));
|
|
163
|
-
notify(generator.jsonToManual(object, false));
|
|
164
|
-
response = await commands["wait-for-image"](
|
|
165
|
-
object.description,
|
|
166
|
-
object.timeout,
|
|
167
|
-
);
|
|
168
|
-
break;
|
|
169
|
-
case "wait-for-text":
|
|
170
|
-
speak(`waiting for ${object.text}`);
|
|
171
|
-
server.broadcast("status", `waiting for ${object.text}`);
|
|
172
|
-
logger.info(generator.jsonToManual(object));
|
|
173
|
-
copy.text = "*****";
|
|
174
|
-
notify(generator.jsonToManual(copy, false));
|
|
175
|
-
response = await commands["wait-for-text"](
|
|
176
|
-
object.text,
|
|
177
|
-
object.timeout,
|
|
178
|
-
object.method,
|
|
179
|
-
);
|
|
180
|
-
break;
|
|
181
|
-
case "scroll-until-text":
|
|
182
|
-
speak(`scrolling until ${object.text}`);
|
|
183
|
-
server.broadcast("status", `scrolling until ${object.text}`);
|
|
184
|
-
logger.info(generator.jsonToManual(object));
|
|
185
|
-
copy.text = "*****";
|
|
186
|
-
notify(generator.jsonToManual(copy, false));
|
|
187
|
-
response = await commands["scroll-until-text"](
|
|
188
|
-
object.text,
|
|
189
|
-
object.direction,
|
|
190
|
-
object.distance,
|
|
191
|
-
object.textMatchMethod,
|
|
192
|
-
object.method,
|
|
193
|
-
);
|
|
194
|
-
break;
|
|
195
|
-
case "scroll-until-image":
|
|
196
|
-
speak(`scrolling until ${object.description}`);
|
|
197
|
-
server.broadcast("status", `scrolling until ${object.description}`);
|
|
198
|
-
logger.info(generator.jsonToManual(object));
|
|
199
|
-
notify(generator.jsonToManual(object, false));
|
|
200
|
-
response = await commands["scroll-until-image"](
|
|
201
|
-
object.description,
|
|
202
|
-
object.direction,
|
|
203
|
-
object.distance,
|
|
204
|
-
object.method,
|
|
205
|
-
);
|
|
206
|
-
break;
|
|
207
|
-
case "focus-application":
|
|
208
|
-
speak(`focusing ${object.name}`);
|
|
209
|
-
server.broadcast("status", `focusing ${object.name}`);
|
|
210
|
-
logger.info(generator.jsonToManual(object));
|
|
211
|
-
notify(generator.jsonToManual(object, false));
|
|
212
|
-
response = await commands["focus-application"](object.name);
|
|
213
|
-
break;
|
|
214
|
-
case "remember":
|
|
215
|
-
{ logger.info(generator.jsonToManual(object));
|
|
216
|
-
notify(generator.jsonToManual(object, false));
|
|
217
|
-
let value = await commands["remember"](object.description);
|
|
218
|
-
console.log(value);
|
|
219
|
-
outputs.set(object.output, value);
|
|
220
|
-
break; }
|
|
221
|
-
case "assert":
|
|
222
|
-
speak(`asserting ${object.expect}`);
|
|
223
|
-
server.broadcast("status", `asserting ${object.expect}`);
|
|
224
|
-
logger.info(generator.jsonToManual(object));
|
|
225
|
-
notify(generator.jsonToManual(object, false));
|
|
226
|
-
response = await commands.assert(object.expect, object.async);
|
|
227
|
-
break;
|
|
228
|
-
case "exec":
|
|
229
|
-
|
|
230
|
-
speak(`exec`);
|
|
231
|
-
server.broadcast("status", `exec`);
|
|
232
|
-
logger.info(generator.jsonToManual(object));
|
|
233
|
-
notify(generator.jsonToManual(object, false));
|
|
234
|
+
outputs.set(object.output, response);
|
|
234
235
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
break;
|
|
240
|
-
default:
|
|
241
|
-
throw new Error(`Command not found: ${object.command}`);
|
|
236
|
+
break;
|
|
237
|
+
default:
|
|
238
|
+
throw new Error(`Command not found: ${object.command}`);
|
|
239
|
+
}
|
|
242
240
|
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
let timing = marky.stop(object.command);
|
|
246
241
|
|
|
247
|
-
|
|
248
|
-
sdk.req("ran", { command: object.command, data: object }),
|
|
249
|
-
analytics.track("command", { data: object, depth, timing }),
|
|
250
|
-
]);
|
|
242
|
+
let timing = marky.stop(object.command);
|
|
251
243
|
|
|
252
|
-
|
|
244
|
+
await Promise.all([
|
|
245
|
+
sdk.req("ran", { command: object.command, data: object }),
|
|
246
|
+
analytics.track("command", { data: object, depth, timing }),
|
|
247
|
+
]);
|
|
253
248
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
249
|
+
return response;
|
|
250
|
+
} catch (error) {
|
|
251
|
+
logger.debug(error);
|
|
252
|
+
throw error;
|
|
253
|
+
}
|
|
254
|
+
};
|
|
259
255
|
|
|
260
256
|
module.exports = { run };
|