testdriverai 4.0.24 → 4.0.26
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/index.js +36 -6
- package/lib/init.js +6 -1
- package/lib/parser.js +36 -1
- package/package.json +2 -1
package/index.js
CHANGED
|
@@ -16,6 +16,7 @@ const http = require('http');
|
|
|
16
16
|
const path = require('path');
|
|
17
17
|
const chalk = require('chalk')
|
|
18
18
|
const yaml = require('js-yaml');
|
|
19
|
+
const sanitizeFilename = require("sanitize-filename");
|
|
19
20
|
const macScreenPerms = require('mac-screen-capture-permissions');
|
|
20
21
|
|
|
21
22
|
// local modules
|
|
@@ -398,6 +399,36 @@ const humanInput = async (currentTask, validateAndLoop = false) => {
|
|
|
398
399
|
|
|
399
400
|
}
|
|
400
401
|
|
|
402
|
+
const generate = async (type) => {
|
|
403
|
+
|
|
404
|
+
log.log('debug', 'generate called', type)
|
|
405
|
+
|
|
406
|
+
speak('thinking...');
|
|
407
|
+
notify('thinking...');
|
|
408
|
+
log.log('info', chalk.dim('thinking...'), true);
|
|
409
|
+
|
|
410
|
+
log.log('info', '');
|
|
411
|
+
|
|
412
|
+
let image = await system.captureScreenBase64();
|
|
413
|
+
let message = await sdk.req('generate', {
|
|
414
|
+
type,
|
|
415
|
+
image});
|
|
416
|
+
|
|
417
|
+
log.prettyMarkdown(message)
|
|
418
|
+
|
|
419
|
+
let testPrompts = await parser.findGenerativePrompts(message);
|
|
420
|
+
|
|
421
|
+
// for each testPrompt
|
|
422
|
+
for (const testPrompt of testPrompts) {
|
|
423
|
+
// write a file called testprompt.headings[0].replace(' ', '-').toLowerCase().md
|
|
424
|
+
// with the contents of the testPrompt
|
|
425
|
+
let fileName = testPrompt.headings[0].trim().replace(/ /g, '-').toLowerCase() + '.md';
|
|
426
|
+
let path1 = path.join(process.cwd(), 'testdriver', '.generate', fileName);
|
|
427
|
+
let contents = testPrompt.listsOrdered[0].map((item, index) => `${index + 1}. /explore ${item}`).join('\n');
|
|
428
|
+
fs.writeFileSync(path1, contents);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
401
432
|
const popFromHistory = async (fullStep) => {
|
|
402
433
|
|
|
403
434
|
log.log('info', chalk.dim('undoing...'), true)
|
|
@@ -501,7 +532,9 @@ const firstPrompt = async (text) => {
|
|
|
501
532
|
analytics.track('input', {input});
|
|
502
533
|
|
|
503
534
|
console.log('') // adds a nice break between submissions
|
|
504
|
-
|
|
535
|
+
|
|
536
|
+
let commands = input.split(' ');
|
|
537
|
+
|
|
505
538
|
// if last character is a question mark, we assume the user is asking a question
|
|
506
539
|
if (input.indexOf('/summarize') == 0) {
|
|
507
540
|
await summarize();
|
|
@@ -510,19 +543,17 @@ const firstPrompt = async (text) => {
|
|
|
510
543
|
} else if (input.indexOf('/save') == 0) {
|
|
511
544
|
await save();
|
|
512
545
|
} else if (input.indexOf('/explore') == 0) {
|
|
513
|
-
let commands = input.split(' ');
|
|
514
546
|
await humanInput(commands.slice(1).join(' '), true)
|
|
515
547
|
} else if (input.indexOf('/undo') == 0) {
|
|
516
548
|
await undo();
|
|
517
549
|
} else if (input.indexOf('/assert') == 0) {
|
|
518
|
-
let commands = input.split(' ');
|
|
519
550
|
await assert(commands.slice(1).join(' '))
|
|
520
551
|
} else if (input.indexOf('/manual') == 0) {
|
|
521
|
-
let commands = input.split(' ');
|
|
522
552
|
await manualInput(commands.slice(1).join(' '))
|
|
523
553
|
} else if (input.indexOf('/run') == 0) {
|
|
524
|
-
let commands = input.split(' ');
|
|
525
554
|
await run(commands[1], commands[2]);
|
|
555
|
+
} else if (input.indexOf('/generate') == 0) {
|
|
556
|
+
await generate(commands[1]);
|
|
526
557
|
} else {
|
|
527
558
|
await humanInput(input, false)
|
|
528
559
|
}
|
|
@@ -747,7 +778,6 @@ const promptUser = () => {
|
|
|
747
778
|
const setTerminalApp = async () => {
|
|
748
779
|
|
|
749
780
|
let win = await system.activeWin();
|
|
750
|
-
console.log(win)
|
|
751
781
|
if (process.platform === 'win32') {
|
|
752
782
|
terminalApp = win?.title || "";
|
|
753
783
|
} else {
|
package/lib/init.js
CHANGED
|
@@ -117,7 +117,7 @@ module.exports = async () => {
|
|
|
117
117
|
await fs.appendFileSync(append, env);
|
|
118
118
|
|
|
119
119
|
|
|
120
|
-
let resolvedPath = await getLatestRelease('
|
|
120
|
+
let resolvedPath = await getLatestRelease('testdriverai', 'testdriver-web');
|
|
121
121
|
|
|
122
122
|
if (resolvedPath) {
|
|
123
123
|
const directory = await decompress(resolvedPath, process.cwd(), {
|
|
@@ -136,6 +136,11 @@ module.exports = async () => {
|
|
|
136
136
|
if (!fs.existsSync(testdriverFolder)) {
|
|
137
137
|
fs.mkdirSync(testdriverFolder);
|
|
138
138
|
}
|
|
139
|
+
|
|
140
|
+
const testdriverGenerateFolder = path.join(process.cwd(), 'testdriver', '.generate');
|
|
141
|
+
if (!fs.existsSync(testdriverGenerateFolder)) {
|
|
142
|
+
fs.mkdirSync(testdriverGenerateFolder);
|
|
143
|
+
}
|
|
139
144
|
}
|
|
140
145
|
|
|
141
146
|
console.log('');
|
package/lib/parser.js
CHANGED
|
@@ -5,7 +5,7 @@ const yaml = require('js-yaml');
|
|
|
5
5
|
let parser = new Parser();
|
|
6
6
|
|
|
7
7
|
// use markdown parser to find code blocks within AI response
|
|
8
|
-
const findCodeBlocks = (markdownContent)
|
|
8
|
+
const findCodeBlocks = async function(markdownContent) {
|
|
9
9
|
|
|
10
10
|
return new Promise((resolve, reject) => {
|
|
11
11
|
parser.parse(markdownContent, (err, result) => {
|
|
@@ -26,6 +26,40 @@ const findCodeBlocks = (markdownContent) => {
|
|
|
26
26
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
// use markdown parser to find code blocks within AI response
|
|
30
|
+
const findGenerativePrompts = async function(markdownContent) {
|
|
31
|
+
|
|
32
|
+
return new Promise((resolve, reject) => {
|
|
33
|
+
parser.parse(markdownContent, async (err, result) => {
|
|
34
|
+
|
|
35
|
+
if (err) {
|
|
36
|
+
return reject(err);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// parse the markdown content of each code block
|
|
40
|
+
let codes = result.codes.map((code) => {
|
|
41
|
+
return new Promise((resolve2, reject2) => {
|
|
42
|
+
parser.parse(code.code, (err, result) => {
|
|
43
|
+
if (err) {
|
|
44
|
+
reject2(err);
|
|
45
|
+
} else {
|
|
46
|
+
resolve2(result);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// use Promise.all to wait for all the promises to resolve
|
|
53
|
+
let parsedCodes = await Promise.all(codes);
|
|
54
|
+
|
|
55
|
+
return resolve(parsedCodes);
|
|
56
|
+
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
|
|
29
63
|
// parse the yml from the included codeblock and clean it up
|
|
30
64
|
const getYAMLFromCodeBlock = function(codeblock) {
|
|
31
65
|
|
|
@@ -58,6 +92,7 @@ const parseYAML = async function(inputYaml) {
|
|
|
58
92
|
|
|
59
93
|
module.exports = {
|
|
60
94
|
findCodeBlocks,
|
|
95
|
+
findGenerativePrompts,
|
|
61
96
|
getYAMLFromCodeBlock,
|
|
62
97
|
getCommands: async function(codeBlock) {
|
|
63
98
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "testdriverai",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.26",
|
|
4
4
|
"description": "Next generation autonomous AI agent for end-to-end testing of web & desktop",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"remark-parse": "^11.0.0",
|
|
36
36
|
"rimraf": "^5.0.5",
|
|
37
37
|
"robotjs": "^0.6.0",
|
|
38
|
+
"sanitize-filename": "^1.6.3",
|
|
38
39
|
"say": "^0.16.0",
|
|
39
40
|
"screenshot-desktop": "^1.15.0",
|
|
40
41
|
"semver": "^7.6.2",
|