testdriverai 4.2.19 → 5.0.0-beta-8
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/.github/dependabot.yml +1 -1
- package/.github/workflows/test_interp.yml +1 -1
- package/.github/workflows/testdriver.yml +28 -0
- package/README.md +3 -2
- package/agent.js +90 -24
- package/electron/overlay.html +39 -5
- package/electron/overlay.js +57 -24
- package/electron/td.png +0 -0
- package/index.js +2 -2
- package/lib/commander.js +10 -2
- package/lib/commands.js +94 -50
- package/lib/config.js +4 -2
- package/lib/events.js +4 -0
- package/lib/focus-application.js +16 -0
- package/lib/generator.js +16 -0
- package/lib/init.js +59 -21
- package/lib/keymaps/sandbox.js +124 -0
- package/lib/logger.js +4 -1
- package/lib/overlay.js +0 -2
- package/lib/redraw.js +3 -1
- package/lib/sandbox.js +64 -0
- package/lib/speak.js +3 -0
- package/lib/system.js +69 -24
- package/lib/websockets.js +78 -0
- package/package-lock.json +8705 -0
- package/package.json +8 -6
- package/test.md +8 -0
- /package/lib/{keymap.js → keymaps/robot.js} +0 -0
package/lib/commands.js
CHANGED
|
@@ -7,7 +7,7 @@ const {
|
|
|
7
7
|
platform,
|
|
8
8
|
activeWin,
|
|
9
9
|
} = require("./system");
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
const { focusApplication } = require("./focus-application");
|
|
12
12
|
const fs = require("fs").promises; // Using the promises version for async operations
|
|
13
13
|
const robot = require("robotjs");
|
|
@@ -18,6 +18,16 @@ const Jimp = require("jimp");
|
|
|
18
18
|
const os = require("os");
|
|
19
19
|
const cliProgress = require("cli-progress");
|
|
20
20
|
const redraw = require("./redraw");
|
|
21
|
+
const sandbox = require("./sandbox.js");
|
|
22
|
+
const config = require("./config.js");
|
|
23
|
+
|
|
24
|
+
let keymap;
|
|
25
|
+
if (config.TD_VM) {
|
|
26
|
+
keymap = require("./keymaps/sandbox.js");
|
|
27
|
+
} else {
|
|
28
|
+
keymap = require("./keymaps/robot.js");
|
|
29
|
+
}
|
|
30
|
+
|
|
21
31
|
const {
|
|
22
32
|
logger,
|
|
23
33
|
prettyMarkdown,
|
|
@@ -177,26 +187,26 @@ const scroll = async (direction = "down", amount = 300, method = "mouse") => {
|
|
|
177
187
|
switch (direction) {
|
|
178
188
|
case "up":
|
|
179
189
|
if (method === "mouse") {
|
|
180
|
-
await robot.scrollMouse(0, amount );
|
|
190
|
+
config.TD_VM ? await sandbox.send({type: "scroll", amount }) : await robot.scrollMouse(0, amount );
|
|
181
191
|
} else {
|
|
182
|
-
await robot.keyTap("pageup");
|
|
192
|
+
config.TD_VM ? await sandbox.send({type: "press", keys: ["pageup"]}) : await robot.keyTap("pageup");
|
|
183
193
|
}
|
|
184
194
|
await redraw.wait(2500);
|
|
185
195
|
break;
|
|
186
196
|
case "down":
|
|
187
197
|
if (method === "mouse") {
|
|
188
|
-
await robot.scrollMouse(0, amount * -1);
|
|
198
|
+
config.TD_VM ? await sandbox.send({type: "scroll", amount: amount * -1}) : await robot.scrollMouse(0, amount * -1);
|
|
189
199
|
} else {
|
|
190
|
-
await robot.keyTap("pagedown");
|
|
200
|
+
config.TD_VM ? await sandbox.send({type: "press", keys: ["pagedown"] }) : await robot.keyTap("pagedown");
|
|
191
201
|
}
|
|
192
202
|
await redraw.wait(2500);
|
|
193
203
|
break;
|
|
194
204
|
case "left":
|
|
195
|
-
await robot.scrollMouse(amount * -1, 0);
|
|
205
|
+
config.TD_VM ? console.log('Not Supported') : await robot.scrollMouse(amount * -1, 0);
|
|
196
206
|
await redraw.wait(2500);
|
|
197
207
|
break;
|
|
198
208
|
case "right":
|
|
199
|
-
await robot.scrollMouse(amount, 0);
|
|
209
|
+
config.TD_VM ? console.log('Not Supported') : await robot.scrollMouse(amount, 0);
|
|
200
210
|
await redraw.wait(2500);
|
|
201
211
|
break;
|
|
202
212
|
default:
|
|
@@ -224,21 +234,32 @@ const click = async (x, y, action = "click") => {
|
|
|
224
234
|
x = parseInt(x);
|
|
225
235
|
y = parseInt(y);
|
|
226
236
|
|
|
227
|
-
robot.moveMouseSmooth(x, y, 0.1);
|
|
228
|
-
|
|
237
|
+
config.TD_VM ? await sandbox.send({type: "moveMouse", x, y }) : await robot.moveMouseSmooth(x, y, 0.1);
|
|
229
238
|
await delay(1000); // wait for the mouse to move
|
|
230
239
|
|
|
231
|
-
if (process.platform === "darwin" && action === "right-click") {
|
|
240
|
+
if (!config.TD_VM && process.platform === "darwin" && action === "right-click") {
|
|
232
241
|
robot.keyToggle('control', 'down', 'control');
|
|
233
242
|
await delay(250);
|
|
234
243
|
}
|
|
235
244
|
|
|
236
245
|
if (action !== "hover") {
|
|
237
|
-
|
|
246
|
+
if (config.TD_VM) {
|
|
247
|
+
if (action === "click" || action === "left-click") {
|
|
248
|
+
await sandbox.send({type: "leftClick" })
|
|
249
|
+
} else if (action === "right-click") {
|
|
250
|
+
await sandbox.send({type: "rightClick" })
|
|
251
|
+
} else if (action === "middle-click") {
|
|
252
|
+
await sandbox.send({type: "middleClick" })
|
|
253
|
+
} else if (action === "double-click") {
|
|
254
|
+
await sandbox.send({type: "doubleClick" })
|
|
255
|
+
}
|
|
256
|
+
} else {
|
|
257
|
+
robot.mouseClick(button, double);
|
|
258
|
+
}
|
|
238
259
|
emitter.emit(events.mouseClick, { x, y, button, click });
|
|
239
260
|
}
|
|
240
261
|
|
|
241
|
-
if (process.platform === "darwin" && action === "right-click") {
|
|
262
|
+
if (!config.TD_VM && process.platform === "darwin" && action === "right-click") {
|
|
242
263
|
await delay(250);
|
|
243
264
|
robot.keyToggle('control', 'up', 'control');
|
|
244
265
|
}
|
|
@@ -253,7 +274,7 @@ const hover = async (x, y) => {
|
|
|
253
274
|
x = parseInt(x);
|
|
254
275
|
y = parseInt(y);
|
|
255
276
|
|
|
256
|
-
await
|
|
277
|
+
await sandbox.send({type: "moveMouse", x, y });
|
|
257
278
|
|
|
258
279
|
await redraw.wait(2500);
|
|
259
280
|
|
|
@@ -364,7 +385,13 @@ let commands = {
|
|
|
364
385
|
// type a string
|
|
365
386
|
type: async (string, delay = 500) => {
|
|
366
387
|
await redraw.start();
|
|
388
|
+
|
|
367
389
|
string = string.toString();
|
|
390
|
+
|
|
391
|
+
if (config.TD_VM) {
|
|
392
|
+
await sandbox.send({type: "write", text: string });
|
|
393
|
+
} else {
|
|
394
|
+
|
|
368
395
|
// there is a bug in robotjs that causes repeated characters to only be typed once
|
|
369
396
|
// so we need to check for repeated characters and type them slowly if so
|
|
370
397
|
const hasRepeatedChars = /(.)\1/.test(string);
|
|
@@ -372,7 +399,8 @@ let commands = {
|
|
|
372
399
|
await robot.typeStringDelayed(string, delay);
|
|
373
400
|
else
|
|
374
401
|
await robot.typeString(string);
|
|
375
|
-
|
|
402
|
+
}
|
|
403
|
+
// await redraw.wait(5000);
|
|
376
404
|
return;
|
|
377
405
|
},
|
|
378
406
|
// press keys
|
|
@@ -395,7 +423,7 @@ let commands = {
|
|
|
395
423
|
key = "control";
|
|
396
424
|
}
|
|
397
425
|
|
|
398
|
-
if (modifierKeys.includes(key)) {
|
|
426
|
+
if (!config.TD_VM && modifierKeys.includes(key)) {
|
|
399
427
|
modifierKeysPressed.push(key);
|
|
400
428
|
} else {
|
|
401
429
|
keysPressed.push(key);
|
|
@@ -411,32 +439,40 @@ let commands = {
|
|
|
411
439
|
});
|
|
412
440
|
|
|
413
441
|
// only one key can be pressed at a time
|
|
414
|
-
if (keysPressed.length > 1) {
|
|
442
|
+
if (!config.TD_VM && keysPressed.length > 1) {
|
|
415
443
|
throw new AiError(
|
|
416
444
|
"Only one key can be pressed at a time. However, multiple modifier keys can be pressed at the same time.",
|
|
417
445
|
);
|
|
418
446
|
}
|
|
419
447
|
|
|
420
448
|
// make sure modifier keys are valid, multiple are allowed
|
|
421
|
-
let modsToPress =
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
449
|
+
let modsToPress = [];
|
|
450
|
+
|
|
451
|
+
if (!config.TD_VM) {
|
|
452
|
+
modifierKeysPressed.map((key) => {
|
|
453
|
+
if (keymap[key] === undefined) {
|
|
454
|
+
logger.error(`Modifier key not found: ${key}`);
|
|
455
|
+
throw new AiError(`Modifier key not found: ${key}`);
|
|
456
|
+
} else {
|
|
457
|
+
return keymap[key];
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
robot.keyTap(keysPressed[0], modsToPress);
|
|
461
|
+
} else {
|
|
462
|
+
await sandbox.send({type: "press", keys: keysPressed });
|
|
463
|
+
}
|
|
429
464
|
|
|
430
465
|
// finally, press the keys
|
|
431
|
-
robot.keyTap(keysPressed[0], modsToPress);
|
|
432
466
|
|
|
433
467
|
await redraw.wait(5000);
|
|
434
468
|
|
|
435
469
|
// keyTap will release the normal keys, but will not release modifier keys
|
|
436
470
|
// so we need to release the modifier keys manually
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
471
|
+
if (!config.TD_VM) {
|
|
472
|
+
modsToPress.forEach((key) => {
|
|
473
|
+
robot.keyToggle(key, "up");
|
|
474
|
+
});
|
|
475
|
+
}
|
|
440
476
|
|
|
441
477
|
return;
|
|
442
478
|
},
|
|
@@ -546,15 +582,18 @@ let commands = {
|
|
|
546
582
|
|
|
547
583
|
if (method === "keyboard") {
|
|
548
584
|
try {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
585
|
+
|
|
586
|
+
if (!config.TD_VM) {
|
|
587
|
+
await robot.keyTap("f", commandOrControl);;
|
|
588
|
+
robot.keyToggle(commandOrControl, "up");
|
|
589
|
+
await robot.typeStringDelayed(text, 500);
|
|
590
|
+
} else {
|
|
591
|
+
await sandbox.send({type: "press", keys: ["f", commandOrControl] })
|
|
592
|
+
await sandbox.send({type: "write", text });
|
|
593
|
+
await redraw.wait(5000);
|
|
594
|
+
await sandbox.send({type: "press", keys: ["escape"] });
|
|
595
|
+
}
|
|
596
|
+
|
|
558
597
|
} catch (e) {
|
|
559
598
|
logger.error("%s", e);
|
|
560
599
|
throw new AiError(
|
|
@@ -666,23 +705,28 @@ let commands = {
|
|
|
666
705
|
},
|
|
667
706
|
exec: async (cli_command, use_stderr = false, silent = false) => {
|
|
668
707
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
}
|
|
708
|
+
if (config.TD_VM) {
|
|
709
|
+
return await sandbox.send({type: "commands.run", commands: cli_command });
|
|
710
|
+
} else {
|
|
673
711
|
|
|
674
|
-
|
|
712
|
+
let args = {};
|
|
713
|
+
if (silent) {
|
|
714
|
+
args = { stdio: [] };
|
|
715
|
+
}
|
|
675
716
|
|
|
676
|
-
|
|
677
|
-
logger.info(chalk.dim(stdout), true);
|
|
678
|
-
}
|
|
717
|
+
const { stdout, stderr } = await exec(cli_command, args);
|
|
679
718
|
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
return stdout;
|
|
684
|
-
}
|
|
719
|
+
if (!silent) {
|
|
720
|
+
logger.info(chalk.dim(stdout), true);
|
|
721
|
+
}
|
|
685
722
|
|
|
723
|
+
if (use_stderr) {
|
|
724
|
+
return stderr;
|
|
725
|
+
} else {
|
|
726
|
+
return stdout;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
}
|
|
686
730
|
}
|
|
687
731
|
};
|
|
688
732
|
|
package/lib/config.js
CHANGED
|
@@ -26,10 +26,12 @@ const config = {
|
|
|
26
26
|
TD_ANALYTICS: true,
|
|
27
27
|
TD_NOTIFY: false,
|
|
28
28
|
TD_MINIMIZE: true,
|
|
29
|
-
TD_API_ROOT: "https://api.
|
|
29
|
+
TD_API_ROOT: "https://replayable-api-production.herokuapp.com",
|
|
30
|
+
TD_API_KEY: null,
|
|
30
31
|
TD_DEV: parseValue(process.env["DEV"]),
|
|
31
32
|
TD_PROFILE: false,
|
|
32
|
-
TD_OVERLAY: true
|
|
33
|
+
TD_OVERLAY: true,
|
|
34
|
+
TD_VM: true
|
|
33
35
|
};
|
|
34
36
|
|
|
35
37
|
// Find all env vars starting with TD_
|
package/lib/events.js
CHANGED
|
@@ -3,6 +3,7 @@ const { EventEmitter } = require("events");
|
|
|
3
3
|
const emitter = new EventEmitter();
|
|
4
4
|
|
|
5
5
|
const events = {
|
|
6
|
+
showWindow: "show-window",
|
|
6
7
|
mouseClick: "mouse-click",
|
|
7
8
|
screenCapture: {
|
|
8
9
|
start: "screen-capture:start",
|
|
@@ -17,6 +18,9 @@ const events = {
|
|
|
17
18
|
matches: {
|
|
18
19
|
show: "matches:show",
|
|
19
20
|
},
|
|
21
|
+
vm: {
|
|
22
|
+
show: "vm:show",
|
|
23
|
+
}
|
|
20
24
|
};
|
|
21
25
|
|
|
22
26
|
const getValues = (obj) => {
|
package/lib/focus-application.js
CHANGED
|
@@ -5,6 +5,22 @@ const { platform } = require("./system");
|
|
|
5
5
|
const scriptPath = path.join(__dirname, "focusWindow.ps1");
|
|
6
6
|
const robot = require("robotjs");
|
|
7
7
|
const { logger } = require("./logger");
|
|
8
|
+
const sandbox = require("./sandbox");
|
|
9
|
+
|
|
10
|
+
async function focusVSCode() {
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
|
|
14
|
+
if (platform() == "mac") {
|
|
15
|
+
return await execSync('open -a "Visual Studio Code"');
|
|
16
|
+
} else {
|
|
17
|
+
return await execSync('"C:\\Program Files\\Microsoft VS Code\\Code.exe"');
|
|
18
|
+
}
|
|
19
|
+
} catch (error) {
|
|
20
|
+
logger.error(error);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
}
|
|
8
24
|
|
|
9
25
|
// apple script that focuses on a window
|
|
10
26
|
const appleScriptSetFrontmost = (windowName) => `
|
package/lib/generator.js
CHANGED
|
@@ -64,6 +64,21 @@ const dumpToYML = async function (inputArray) {
|
|
|
64
64
|
|
|
65
65
|
return yml;
|
|
66
66
|
};
|
|
67
|
+
const rawToFormatted = async function (inputCommands) {
|
|
68
|
+
// inputCommands is raw yml
|
|
69
|
+
|
|
70
|
+
let json = await yaml.load(inputCommands);
|
|
71
|
+
// use yml dump to convert json to yml
|
|
72
|
+
let yml = await yaml.dump({
|
|
73
|
+
version: package.version,
|
|
74
|
+
session: session.get(),
|
|
75
|
+
steps: [
|
|
76
|
+
{commands: json.commands},
|
|
77
|
+
],
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
return yml;
|
|
81
|
+
};
|
|
67
82
|
|
|
68
83
|
const hydrateFromYML = async function (yml) {
|
|
69
84
|
// use yml load to convert yml to json
|
|
@@ -79,4 +94,5 @@ module.exports = {
|
|
|
79
94
|
dumpToYML,
|
|
80
95
|
hydrateFromYML,
|
|
81
96
|
jsonToManual,
|
|
97
|
+
rawToFormatted
|
|
82
98
|
};
|
package/lib/init.js
CHANGED
|
@@ -8,6 +8,12 @@ const chalk = require("chalk");
|
|
|
8
8
|
const { Readable } = require("stream");
|
|
9
9
|
const { logger } = require("./logger");
|
|
10
10
|
|
|
11
|
+
const validateUUID = (uuid) => {
|
|
12
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
13
|
+
return uuidRegex.test(uuid);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
|
|
11
17
|
async function getLatestRelease(owner, repo) {
|
|
12
18
|
try {
|
|
13
19
|
const response = await fetch(
|
|
@@ -69,26 +75,32 @@ module.exports = async () => {
|
|
|
69
75
|
logger.info("");
|
|
70
76
|
|
|
71
77
|
const response = await prompts([
|
|
72
|
-
// {
|
|
73
|
-
// type: 'password',
|
|
74
|
-
// name: 'DASHCAM_API_KEY',
|
|
75
|
-
// message: 'API KEY (from https://app.dashcam.io/team)',
|
|
76
|
-
// // validate: value => (validate(value) ? true : 'Invalid API Key')
|
|
77
|
-
// },
|
|
78
78
|
{
|
|
79
79
|
type: "confirm",
|
|
80
|
-
name: "
|
|
81
|
-
message: "
|
|
80
|
+
name: "TD_VM",
|
|
81
|
+
message: "Use Testdriver Runners? (Recommended)",
|
|
82
82
|
initial: true,
|
|
83
83
|
},
|
|
84
84
|
{
|
|
85
|
-
type: "
|
|
85
|
+
type: prev => (prev ? "password" : null),
|
|
86
|
+
name: 'TD_API_KEY',
|
|
87
|
+
message: 'API KEY (from https://app.testdriver.ai/team)',
|
|
88
|
+
validate: value => (validateUUID(value) ? true : 'Invalid API Key')
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
type: prev => (prev ? null : "confirm"),
|
|
86
92
|
name: "TD_MINIMIZE",
|
|
87
93
|
message: "Minimize terminal app?",
|
|
88
94
|
initial: true,
|
|
89
95
|
},
|
|
90
96
|
{
|
|
91
|
-
type: "confirm",
|
|
97
|
+
type: prev => (prev ? null : "confirm"),
|
|
98
|
+
name: "TD_NOTIFY",
|
|
99
|
+
message: "Enable desktop notifications?",
|
|
100
|
+
initial: true,
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
type: prev => (prev ? null : "confirm"),
|
|
92
104
|
name: "TD_SPEAK",
|
|
93
105
|
message: "Enable text to speech narration?",
|
|
94
106
|
initial: true,
|
|
@@ -98,26 +110,19 @@ module.exports = async () => {
|
|
|
98
110
|
name: "TD_ANALYTICS",
|
|
99
111
|
message: "Send anonymous analytics?",
|
|
100
112
|
initial: true,
|
|
101
|
-
}
|
|
102
|
-
{
|
|
103
|
-
type: "text",
|
|
104
|
-
name: "APPEND",
|
|
105
|
-
message: "Where should we append these values?",
|
|
106
|
-
initial: ".env",
|
|
107
|
-
},
|
|
113
|
+
}
|
|
108
114
|
]);
|
|
109
115
|
|
|
110
116
|
logger.info("");
|
|
111
|
-
logger.info(chalk.dim(`Writing
|
|
117
|
+
logger.info(chalk.dim(`Writing .env...`));
|
|
112
118
|
logger.info("");
|
|
113
119
|
logger.info(`Downloading latest workflow files...`);
|
|
114
120
|
logger.info("");
|
|
115
121
|
|
|
116
122
|
const env = Object.entries(response)
|
|
117
|
-
.filter(([key]) => key !== "APPEND")
|
|
118
123
|
.map(([key, value]) => `${key}=${value}`)
|
|
119
124
|
.join("\n");
|
|
120
|
-
const append = path.join(process.cwd(),
|
|
125
|
+
const append = path.join(process.cwd(), '.env');
|
|
121
126
|
|
|
122
127
|
if (!fs.existsSync(append)) {
|
|
123
128
|
await fs.writeFileSync(append, "");
|
|
@@ -153,11 +158,44 @@ module.exports = async () => {
|
|
|
153
158
|
if (!fs.existsSync(testdriverGenerateFolder)) {
|
|
154
159
|
fs.mkdirSync(testdriverGenerateFolder);
|
|
155
160
|
}
|
|
161
|
+
|
|
162
|
+
const tdScreen = path.join(
|
|
163
|
+
process.cwd(),
|
|
164
|
+
"testdriver",
|
|
165
|
+
"screenshots"
|
|
166
|
+
);
|
|
167
|
+
if (!fs.existsSync(tdScreen)) {
|
|
168
|
+
fs.mkdirSync(tdScreen);
|
|
169
|
+
}
|
|
170
|
+
const tdScreenMac = path.join(
|
|
171
|
+
process.cwd(),
|
|
172
|
+
"testdriver",
|
|
173
|
+
"screenshots", "mac"
|
|
174
|
+
);
|
|
175
|
+
if (!fs.existsSync(tdScreenMac)) {
|
|
176
|
+
fs.mkdirSync(tdScreenMac);
|
|
177
|
+
}
|
|
178
|
+
const tdScreenWindows = path.join(
|
|
179
|
+
process.cwd(),
|
|
180
|
+
"testdriver",
|
|
181
|
+
"screenshots", "windows"
|
|
182
|
+
);
|
|
183
|
+
if (!fs.existsSync(tdScreenWindows)) {
|
|
184
|
+
fs.mkdirSync(tdScreenWindows);
|
|
185
|
+
}
|
|
186
|
+
const tdScreenLinux = path.join(
|
|
187
|
+
process.cwd(),
|
|
188
|
+
"testdriver",
|
|
189
|
+
"screenshots", "linux"
|
|
190
|
+
);
|
|
191
|
+
if (!fs.existsSync(tdScreenLinux)) {
|
|
192
|
+
fs.mkdirSync(tdScreenLinux);
|
|
193
|
+
}
|
|
156
194
|
}
|
|
157
195
|
|
|
158
196
|
logger.info("");
|
|
159
197
|
logger.info(chalk.green("Testdriver setup complete!"));
|
|
160
198
|
logger.info("");
|
|
161
199
|
logger.info(chalk.yellow("Create a new test by running:"));
|
|
162
|
-
logger.info("testdriverai testdriver/test.
|
|
200
|
+
logger.info("testdriverai testdriver/test.yaml");
|
|
163
201
|
};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// the ai somtimes hallucinates keys
|
|
2
|
+
// so this allows us to map common hallucinations to the correct key
|
|
3
|
+
// doesn't seem like we're making use of this yet
|
|
4
|
+
module.exports = module.exports = {
|
|
5
|
+
backspace: "backspace",
|
|
6
|
+
delete: "delete",
|
|
7
|
+
enter: "enter",
|
|
8
|
+
tab: "tab",
|
|
9
|
+
escape: "escape",
|
|
10
|
+
up: "up",
|
|
11
|
+
down: "down",
|
|
12
|
+
right: "right",
|
|
13
|
+
left: "left",
|
|
14
|
+
home: "home",
|
|
15
|
+
end: "end",
|
|
16
|
+
pageup: "pageup",
|
|
17
|
+
pagedown: "pagedown",
|
|
18
|
+
f1: "f1",
|
|
19
|
+
f2: "f2",
|
|
20
|
+
f3: "f3",
|
|
21
|
+
f4: "f4",
|
|
22
|
+
f5: "f5",
|
|
23
|
+
f6: "f6",
|
|
24
|
+
f7: "f7",
|
|
25
|
+
f8: "f8",
|
|
26
|
+
f9: "f9",
|
|
27
|
+
f10: "f10",
|
|
28
|
+
f11: "f11",
|
|
29
|
+
f12: "f12",
|
|
30
|
+
f13: "f13",
|
|
31
|
+
f14: "f14",
|
|
32
|
+
f15: "f15",
|
|
33
|
+
f16: "f16",
|
|
34
|
+
f17: "f17",
|
|
35
|
+
f18: "f18",
|
|
36
|
+
f19: "f19",
|
|
37
|
+
f20: "f20",
|
|
38
|
+
f21: "f21",
|
|
39
|
+
f22: "f22",
|
|
40
|
+
f23: "f23",
|
|
41
|
+
f24: "f24",
|
|
42
|
+
capslock: "capslock",
|
|
43
|
+
command: "command",
|
|
44
|
+
alt: "alt",
|
|
45
|
+
right_alt: "right_alt",
|
|
46
|
+
control: "ctrl",
|
|
47
|
+
left_control: "left_control",
|
|
48
|
+
right_control: "right_control",
|
|
49
|
+
shift: "shift",
|
|
50
|
+
right_shift: "right_shift",
|
|
51
|
+
space: "space",
|
|
52
|
+
printscreen: "printscreen",
|
|
53
|
+
insert: "insert",
|
|
54
|
+
menu: "menu",
|
|
55
|
+
audio_mute: "audio_mute",
|
|
56
|
+
audio_vol_down: "audio_vol_down",
|
|
57
|
+
audio_vol_up: "audio_vol_up",
|
|
58
|
+
audio_play: "audio_play",
|
|
59
|
+
audio_stop: "audio_stop",
|
|
60
|
+
audio_pause: "audio_pause",
|
|
61
|
+
audio_prev: "audio_prev",
|
|
62
|
+
audio_next: "audio_next",
|
|
63
|
+
audio_rewind: "audio_rewind",
|
|
64
|
+
audio_forward: "audio_forward",
|
|
65
|
+
audio_repeat: "audio_repeat",
|
|
66
|
+
audio_random: "audio_random",
|
|
67
|
+
numpad_lock: "numpad_lock",
|
|
68
|
+
numpad_0: "numpad_0",
|
|
69
|
+
numpad_1: "numpad_1",
|
|
70
|
+
numpad_2: "numpad_2",
|
|
71
|
+
numpad_3: "numpad_3",
|
|
72
|
+
numpad_4: "numpad_4",
|
|
73
|
+
numpad_5: "numpad_5",
|
|
74
|
+
numpad_6: "numpad_6",
|
|
75
|
+
numpad_7: "numpad_7",
|
|
76
|
+
numpad_8: "numpad_8",
|
|
77
|
+
numpad_9: "numpad_9",
|
|
78
|
+
"numpad_+": "numpad_+",
|
|
79
|
+
"numpad_-": "numpad_-",
|
|
80
|
+
"numpad_*": "numpad_*",
|
|
81
|
+
"numpad_/": "numpad_/",
|
|
82
|
+
"numpad_.": "numpad_.",
|
|
83
|
+
lights_mon_up: "lights_mon_up",
|
|
84
|
+
lights_mon_down: "lights_mon_down",
|
|
85
|
+
lights_kbd_toggle: "lights_kbd_toggle",
|
|
86
|
+
lights_kbd_up: "lights_kbd_up",
|
|
87
|
+
lights_kbd_down: "lights_kbd_down",
|
|
88
|
+
a: "a",
|
|
89
|
+
b: "b",
|
|
90
|
+
c: "c",
|
|
91
|
+
d: "d",
|
|
92
|
+
e: "e",
|
|
93
|
+
f: "f",
|
|
94
|
+
g: "g",
|
|
95
|
+
h: "h",
|
|
96
|
+
i: "i",
|
|
97
|
+
j: "j",
|
|
98
|
+
k: "k",
|
|
99
|
+
l: "l",
|
|
100
|
+
m: "m",
|
|
101
|
+
n: "n",
|
|
102
|
+
o: "o",
|
|
103
|
+
p: "p",
|
|
104
|
+
q: "q",
|
|
105
|
+
r: "r",
|
|
106
|
+
s: "s",
|
|
107
|
+
t: "t",
|
|
108
|
+
u: "u",
|
|
109
|
+
v: "v",
|
|
110
|
+
w: "w",
|
|
111
|
+
x: "x",
|
|
112
|
+
y: "y",
|
|
113
|
+
z: "z",
|
|
114
|
+
0: "0",
|
|
115
|
+
1: "1",
|
|
116
|
+
2: "2",
|
|
117
|
+
3: "3",
|
|
118
|
+
4: "4",
|
|
119
|
+
5: "5",
|
|
120
|
+
6: "6",
|
|
121
|
+
7: "7",
|
|
122
|
+
8: "8",
|
|
123
|
+
9: "9",
|
|
124
|
+
};
|
package/lib/logger.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// central logger for the bot
|
|
2
2
|
const winston = require("winston");
|
|
3
3
|
const os = require("os");
|
|
4
|
+
const websockets = require("./websockets");
|
|
4
5
|
|
|
5
6
|
// simple match for aws instance i-*
|
|
6
7
|
const shouldLog =
|
|
@@ -74,7 +75,9 @@ const createMarkdownStreamLogger = () => {
|
|
|
74
75
|
log: (chunk) => {
|
|
75
76
|
if (typeof chunk !== "string") {
|
|
76
77
|
return;
|
|
77
|
-
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
websockets.sendToClients("output", chunk);
|
|
78
81
|
|
|
79
82
|
const previousConsoleOutput = markedParsePartial(buffer, 0, -1);
|
|
80
83
|
|
package/lib/overlay.js
CHANGED
package/lib/redraw.js
CHANGED
|
@@ -146,7 +146,9 @@ async function checkCondition(resolve, startTime, timeoutMs) {
|
|
|
146
146
|
logger.debug(` `);
|
|
147
147
|
resolve("true");
|
|
148
148
|
} else {
|
|
149
|
-
|
|
149
|
+
setTimeout(() => {
|
|
150
|
+
checkCondition(resolve, startTime, timeoutMs);
|
|
151
|
+
}, 500);
|
|
150
152
|
}
|
|
151
153
|
}
|
|
152
154
|
|