testdriverai 4.2.9 → 4.2.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/.github/workflows/format.yml +1 -1
- package/agent.js +91 -96
- package/index.js +2 -1
- package/lib/commander.js +18 -18
- package/lib/commands.js +34 -37
- package/lib/config.js +2 -1
- package/lib/focus-application.js +4 -3
- package/lib/history.js +4 -4
- package/lib/init.js +22 -21
- package/lib/logger.js +42 -66
- package/lib/overlay.js +3 -2
- package/lib/redraw.js +7 -7
- package/lib/sdk.js +5 -5
- package/lib/subimage/index.js +3 -2
- package/lib/system.js +3 -1
- package/package.json +1 -1
package/agent.js
CHANGED
|
@@ -49,6 +49,8 @@ const session = require("./lib/session.js");
|
|
|
49
49
|
const notify = require("./lib/notify.js");
|
|
50
50
|
const { emitter, events } = require("./lib/events.js");
|
|
51
51
|
|
|
52
|
+
const logger = log.logger;
|
|
53
|
+
|
|
52
54
|
let lastPrompt = "";
|
|
53
55
|
let terminalApp = "";
|
|
54
56
|
let commandHistory = [];
|
|
@@ -84,7 +86,7 @@ let getArgs = () => {
|
|
|
84
86
|
args[file] == "--help" ||
|
|
85
87
|
args[file] == "-h"
|
|
86
88
|
) {
|
|
87
|
-
|
|
89
|
+
logger.info("Command: testdriverai [init, run, edit] [yaml filepath]");
|
|
88
90
|
process.exit(0);
|
|
89
91
|
}
|
|
90
92
|
|
|
@@ -123,13 +125,13 @@ let a = getArgs();
|
|
|
123
125
|
const thisFile = a.file;
|
|
124
126
|
const thisCommand = a.command;
|
|
125
127
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
128
|
+
logger.info(chalk.green(`Howdy! I'm TestDriver v${package.version}`));
|
|
129
|
+
logger.info(chalk.dim(`Working on ${thisFile}`));
|
|
130
|
+
logger.info("");
|
|
131
|
+
logger.info(chalk.yellow(`This is beta software!`));
|
|
132
|
+
logger.info(`Join our Discord for help`);
|
|
133
|
+
logger.info(`https://discord.com/invite/cWDFW8DzPm`);
|
|
134
|
+
logger.info("");
|
|
133
135
|
|
|
134
136
|
// individual run ID for this session
|
|
135
137
|
// let runID = new Date().getTime();
|
|
@@ -159,7 +161,7 @@ function fileCompleter(line) {
|
|
|
159
161
|
|
|
160
162
|
return [matches.length ? matches : files, partial];
|
|
161
163
|
} catch (e) {
|
|
162
|
-
|
|
164
|
+
logger.info("%s", e);
|
|
163
165
|
return [[], partial];
|
|
164
166
|
}
|
|
165
167
|
}
|
|
@@ -219,8 +221,7 @@ const exit = async (failed = true, shouldSave = false) => {
|
|
|
219
221
|
};
|
|
220
222
|
|
|
221
223
|
const dieOnFatal = async (error) => {
|
|
222
|
-
|
|
223
|
-
log.log("info", chalk.red("Fatal Error") + `\n${error.message}`);
|
|
224
|
+
logger.error(chalk.red("Fatal Error") + `\n${error.message}`);
|
|
224
225
|
await summarize(error.message);
|
|
225
226
|
return await exit(true);
|
|
226
227
|
};
|
|
@@ -238,19 +239,17 @@ const haveAIResolveError = async (error, markdown, depth = 0, undo = true) => {
|
|
|
238
239
|
let safeKey = JSON.stringify(eMessage);
|
|
239
240
|
errorCounts[safeKey] = errorCounts[safeKey] ? errorCounts[safeKey] + 1 : 1;
|
|
240
241
|
|
|
241
|
-
|
|
242
|
+
logger.error(eMessage);
|
|
242
243
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
console.log(error.stack);
|
|
246
|
-
}
|
|
244
|
+
logger.debug("%j", error);
|
|
245
|
+
logger.debug("%s", error.stack);
|
|
247
246
|
|
|
248
247
|
log.prettyMarkdown(eMessage);
|
|
249
248
|
|
|
250
249
|
// if we get the same error 3 times in `run` mode, we exit
|
|
251
250
|
if (errorCounts[safeKey] > errorLimit - 1) {
|
|
252
|
-
|
|
253
|
-
|
|
251
|
+
logger.info(chalk.red("Error loop detected. Exiting."));
|
|
252
|
+
logger.info("%s", eMessage);
|
|
254
253
|
await summarize(eMessage);
|
|
255
254
|
return await exit(true);
|
|
256
255
|
}
|
|
@@ -268,8 +267,8 @@ const haveAIResolveError = async (error, markdown, depth = 0, undo = true) => {
|
|
|
268
267
|
|
|
269
268
|
speak("thinking...");
|
|
270
269
|
notify("thinking...");
|
|
271
|
-
|
|
272
|
-
|
|
270
|
+
logger.info(chalk.dim("thinking..."), true);
|
|
271
|
+
logger.info("");
|
|
273
272
|
|
|
274
273
|
const mdStream = log.createMarkdownStreamLogger();
|
|
275
274
|
|
|
@@ -300,14 +299,14 @@ const check = async () => {
|
|
|
300
299
|
checkCount++;
|
|
301
300
|
|
|
302
301
|
if (checkCount >= checkLimit) {
|
|
303
|
-
|
|
302
|
+
logger.info(chalk.red("Exploratory loop detected. Exiting."));
|
|
304
303
|
await summarize("Check loop detected.");
|
|
305
304
|
return await exit(true);
|
|
306
305
|
}
|
|
307
306
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
307
|
+
logger.info("");
|
|
308
|
+
logger.info(chalk.dim("checking..."), "testdriver");
|
|
309
|
+
logger.info("");
|
|
311
310
|
|
|
312
311
|
let thisScreenshot = await system.captureScreenBase64(1, false, true);
|
|
313
312
|
let images = [lastScreenshot, thisScreenshot];
|
|
@@ -342,7 +341,7 @@ const check = async () => {
|
|
|
342
341
|
const runCommand = async (command, depth) => {
|
|
343
342
|
let yml = await yaml.dump(command);
|
|
344
343
|
|
|
345
|
-
|
|
344
|
+
logger.debug(`running command: \n\n${yml}`);
|
|
346
345
|
|
|
347
346
|
try {
|
|
348
347
|
let response;
|
|
@@ -378,6 +377,7 @@ let csv = [["command,time"]];
|
|
|
378
377
|
|
|
379
378
|
const executeCommands = async (commands, depth, pushToHistory = false) => {
|
|
380
379
|
if (commands?.length) {
|
|
380
|
+
|
|
381
381
|
for (const command of commands) {
|
|
382
382
|
if (pushToHistory) {
|
|
383
383
|
executionHistory[executionHistory.length - 1]?.commands.push(command);
|
|
@@ -386,7 +386,7 @@ const executeCommands = async (commands, depth, pushToHistory = false) => {
|
|
|
386
386
|
await runCommand(command, depth);
|
|
387
387
|
|
|
388
388
|
let timeToComplete = (new Date().getTime() - lastCommand) / 1000;
|
|
389
|
-
//
|
|
389
|
+
// logger.info(timeToComplete, 'seconds')
|
|
390
390
|
|
|
391
391
|
csv.push([command.command, timeToComplete]);
|
|
392
392
|
lastCommand = new Date().getTime();
|
|
@@ -399,7 +399,7 @@ const executeCommands = async (commands, depth, pushToHistory = false) => {
|
|
|
399
399
|
const executeCodeBlocks = async (codeblocks, depth, pushToHistory = false) => {
|
|
400
400
|
depth = depth + 1;
|
|
401
401
|
|
|
402
|
-
|
|
402
|
+
logger.debug("%j", { message: "execute code blocks", depth });
|
|
403
403
|
|
|
404
404
|
for (const codeblock of codeblocks) {
|
|
405
405
|
let commands;
|
|
@@ -424,13 +424,13 @@ const executeCodeBlocks = async (codeblocks, depth, pushToHistory = false) => {
|
|
|
424
424
|
const aiExecute = async (message, validateAndLoop = false) => {
|
|
425
425
|
executionHistory.push({ prompt: lastPrompt, commands: [] });
|
|
426
426
|
|
|
427
|
-
|
|
427
|
+
logger.debug("kicking off exploratory loop");
|
|
428
428
|
|
|
429
429
|
// kick everything off
|
|
430
430
|
await actOnMarkdown(message, 0, true);
|
|
431
431
|
|
|
432
432
|
if (validateAndLoop) {
|
|
433
|
-
|
|
433
|
+
logger.debug("exploratory loop resolved, check your work");
|
|
434
434
|
|
|
435
435
|
let response = await check();
|
|
436
436
|
|
|
@@ -441,13 +441,13 @@ const aiExecute = async (message, validateAndLoop = false) => {
|
|
|
441
441
|
return await haveAIResolveError(error, response, 0);
|
|
442
442
|
}
|
|
443
443
|
|
|
444
|
-
|
|
444
|
+
logger.debug(`found ${checkCodeblocks.length} codeblocks`);
|
|
445
445
|
|
|
446
446
|
if (checkCodeblocks.length > 0) {
|
|
447
|
-
|
|
447
|
+
logger.debug("check thinks more needs to be done");
|
|
448
448
|
return await aiExecute(response, validateAndLoop);
|
|
449
449
|
} else {
|
|
450
|
-
|
|
450
|
+
logger.debug("seems complete, returning");
|
|
451
451
|
return response;
|
|
452
452
|
}
|
|
453
453
|
}
|
|
@@ -469,8 +469,8 @@ const assert = async (expect) => {
|
|
|
469
469
|
|
|
470
470
|
speak("thinking...");
|
|
471
471
|
notify("thinking...");
|
|
472
|
-
|
|
473
|
-
|
|
472
|
+
logger.info(chalk.dim("thinking..."), true);
|
|
473
|
+
logger.info("");
|
|
474
474
|
|
|
475
475
|
let response = `\`\`\`yml
|
|
476
476
|
commands:
|
|
@@ -489,14 +489,14 @@ const humanInput = async (currentTask, validateAndLoop = false) => {
|
|
|
489
489
|
lastPrompt = currentTask;
|
|
490
490
|
checkCount = 0;
|
|
491
491
|
|
|
492
|
-
|
|
492
|
+
logger.debug("humanInput called");
|
|
493
493
|
|
|
494
494
|
tasks.push(currentTask);
|
|
495
495
|
|
|
496
496
|
speak("thinking...");
|
|
497
497
|
notify("thinking...");
|
|
498
|
-
|
|
499
|
-
|
|
498
|
+
logger.info(chalk.dim("thinking..."), true);
|
|
499
|
+
logger.info("");
|
|
500
500
|
|
|
501
501
|
lastScreenshot = await system.captureScreenBase64();
|
|
502
502
|
|
|
@@ -519,19 +519,19 @@ const humanInput = async (currentTask, validateAndLoop = false) => {
|
|
|
519
519
|
|
|
520
520
|
await aiExecute(message.data, validateAndLoop);
|
|
521
521
|
|
|
522
|
-
|
|
522
|
+
logger.debug("showing prompt from humanInput response check");
|
|
523
523
|
|
|
524
524
|
await save({ silent: true });
|
|
525
525
|
};
|
|
526
526
|
|
|
527
527
|
const generate = async (type, count) => {
|
|
528
|
-
|
|
528
|
+
logger.debug("generate called, %s", type);
|
|
529
529
|
|
|
530
530
|
speak("thinking...");
|
|
531
531
|
notify("thinking...");
|
|
532
532
|
|
|
533
|
-
|
|
534
|
-
|
|
533
|
+
logger.info(chalk.dim("thinking..."), true);
|
|
534
|
+
logger.info("");
|
|
535
535
|
|
|
536
536
|
let image = await system.captureScreenBase64();
|
|
537
537
|
const mdStream = log.createMarkdownStreamLogger();
|
|
@@ -583,7 +583,7 @@ const generate = async (type, count) => {
|
|
|
583
583
|
};
|
|
584
584
|
|
|
585
585
|
const popFromHistory = async (fullStep) => {
|
|
586
|
-
|
|
586
|
+
logger.info(chalk.dim("undoing..."), true);
|
|
587
587
|
|
|
588
588
|
if (executionHistory.length) {
|
|
589
589
|
if (fullStep) {
|
|
@@ -620,7 +620,7 @@ ${yml}
|
|
|
620
620
|
|
|
621
621
|
// this function is responsible for starting the recursive process of executing codeblocks
|
|
622
622
|
const actOnMarkdown = async (content, depth, pushToHistory = false) => {
|
|
623
|
-
|
|
623
|
+
logger.debug("%j", {
|
|
624
624
|
message: "actOnMarkdown called",
|
|
625
625
|
depth,
|
|
626
626
|
});
|
|
@@ -692,7 +692,7 @@ const firstPrompt = async () => {
|
|
|
692
692
|
|
|
693
693
|
analytics.track("input", { input });
|
|
694
694
|
|
|
695
|
-
|
|
695
|
+
logger.info(""); // adds a nice break between submissions
|
|
696
696
|
|
|
697
697
|
let commands = input.split(" ");
|
|
698
698
|
|
|
@@ -732,8 +732,8 @@ const firstPrompt = async () => {
|
|
|
732
732
|
|
|
733
733
|
if (!object?.steps) {
|
|
734
734
|
analytics.track("load invalid yaml");
|
|
735
|
-
|
|
736
|
-
|
|
735
|
+
logger.error("Invalid YAML. No steps found.");
|
|
736
|
+
logger.info("Invalid YAML: " + thisFile);
|
|
737
737
|
return await exit(true);
|
|
738
738
|
}
|
|
739
739
|
|
|
@@ -748,7 +748,7 @@ const firstPrompt = async () => {
|
|
|
748
748
|
${yml}
|
|
749
749
|
\`\`\``;
|
|
750
750
|
|
|
751
|
-
|
|
751
|
+
logger.info(`Loaded test script ${thisFile}\n`);
|
|
752
752
|
|
|
753
753
|
log.prettyMarkdown(`
|
|
754
754
|
|
|
@@ -770,7 +770,7 @@ let setTerminalWindowTransparency = async (hide) => {
|
|
|
770
770
|
.end();
|
|
771
771
|
} catch (e) {
|
|
772
772
|
// Suppress error
|
|
773
|
-
|
|
773
|
+
logger.error("Caught exception: %s", e);
|
|
774
774
|
}
|
|
775
775
|
} else {
|
|
776
776
|
try {
|
|
@@ -780,7 +780,7 @@ let setTerminalWindowTransparency = async (hide) => {
|
|
|
780
780
|
.end();
|
|
781
781
|
} catch (e) {
|
|
782
782
|
// Suppress error
|
|
783
|
-
|
|
783
|
+
logger.error("Caught exception:", e);
|
|
784
784
|
}
|
|
785
785
|
}
|
|
786
786
|
|
|
@@ -800,23 +800,23 @@ let setTerminalWindowTransparency = async (hide) => {
|
|
|
800
800
|
}
|
|
801
801
|
} catch (e) {
|
|
802
802
|
// Suppress error
|
|
803
|
-
|
|
803
|
+
logger.error("Caught exception: %s", e);
|
|
804
804
|
}
|
|
805
805
|
};
|
|
806
806
|
|
|
807
807
|
// this function is responsible for summarizing the test script that has already executed
|
|
808
|
-
// it is what is saved to the `/tmp/oiResult.log
|
|
808
|
+
// it is what is saved to the `/tmp/oiResult.log` file and output to the action as a summary
|
|
809
809
|
let summarize = async (error = null) => {
|
|
810
810
|
analytics.track("summarize");
|
|
811
811
|
|
|
812
|
-
|
|
812
|
+
logger.info("");
|
|
813
813
|
|
|
814
|
-
|
|
814
|
+
logger.info(chalk.dim("reviewing test..."), true);
|
|
815
815
|
|
|
816
816
|
// let text = prompts.summarize(tasks, error);
|
|
817
817
|
let image = await system.captureScreenBase64();
|
|
818
818
|
|
|
819
|
-
|
|
819
|
+
logger.info(chalk.dim("summarizing..."), true);
|
|
820
820
|
|
|
821
821
|
const mdStream = log.createMarkdownStreamLogger();
|
|
822
822
|
let reply = await sdk.req(
|
|
@@ -834,11 +834,11 @@ let summarize = async (error = null) => {
|
|
|
834
834
|
);
|
|
835
835
|
mdStream.end();
|
|
836
836
|
|
|
837
|
-
let resultFile = "/tmp/oiResult.log
|
|
837
|
+
let resultFile = "/tmp/oiResult.log";
|
|
838
838
|
if (process.platform === "win32") {
|
|
839
|
-
resultFile = "/Windows/Temp/oiResult.log
|
|
839
|
+
resultFile = "/Windows/Temp/oiResult.log";
|
|
840
840
|
}
|
|
841
|
-
// write reply to /tmp/oiResult.log
|
|
841
|
+
// write reply to /tmp/oiResult.log
|
|
842
842
|
fs.writeFileSync(resultFile, reply.data);
|
|
843
843
|
};
|
|
844
844
|
|
|
@@ -848,21 +848,21 @@ let save = async ({ filepath = thisFile, silent = false } = {}) => {
|
|
|
848
848
|
analytics.track("save", { silent });
|
|
849
849
|
|
|
850
850
|
if (!silent) {
|
|
851
|
-
|
|
852
|
-
|
|
851
|
+
logger.info(chalk.dim("saving..."), true);
|
|
852
|
+
logger.info("");
|
|
853
853
|
}
|
|
854
854
|
|
|
855
855
|
if (!executionHistory.length) {
|
|
856
856
|
return;
|
|
857
857
|
}
|
|
858
858
|
|
|
859
|
-
// write reply to /tmp/oiResult.log
|
|
859
|
+
// write reply to /tmp/oiResult.log
|
|
860
860
|
let regression = await generator.dumpToYML(executionHistory);
|
|
861
861
|
try {
|
|
862
862
|
fs.writeFileSync(filepath, regression);
|
|
863
863
|
} catch (e) {
|
|
864
|
-
|
|
865
|
-
|
|
864
|
+
logger.error(e.message);
|
|
865
|
+
logger.error("%s", e);
|
|
866
866
|
}
|
|
867
867
|
|
|
868
868
|
if (!silent) {
|
|
@@ -872,11 +872,11 @@ let save = async ({ filepath = thisFile, silent = false } = {}) => {
|
|
|
872
872
|
${regression}
|
|
873
873
|
\`\`\``);
|
|
874
874
|
|
|
875
|
-
//
|
|
875
|
+
// logger.info(csv.join('\n'))
|
|
876
876
|
|
|
877
877
|
const fileName = filepath.split("/").pop();
|
|
878
878
|
if (!silent) {
|
|
879
|
-
|
|
879
|
+
logger.info(chalk.dim(`saved as ${fileName}`));
|
|
880
880
|
}
|
|
881
881
|
}
|
|
882
882
|
};
|
|
@@ -891,7 +891,7 @@ let run = async (file, shouldSave = false, shouldExit = true) => {
|
|
|
891
891
|
setTerminalWindowTransparency(true);
|
|
892
892
|
emitter.emit(events.interactive, false);
|
|
893
893
|
|
|
894
|
-
|
|
894
|
+
logger.info(chalk.cyan(`running ${file}...`));
|
|
895
895
|
|
|
896
896
|
executionHistory = [];
|
|
897
897
|
let yml;
|
|
@@ -900,10 +900,9 @@ let run = async (file, shouldSave = false, shouldExit = true) => {
|
|
|
900
900
|
try {
|
|
901
901
|
yml = fs.readFileSync(file, "utf-8");
|
|
902
902
|
} catch (e) {
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
console.log(`Current directory: ${process.cwd()}`);
|
|
903
|
+
logger.error(e);
|
|
904
|
+
logger.error(`File not found: ${file}`);
|
|
905
|
+
logger.error(`Current directory: ${process.cwd()}`);
|
|
907
906
|
|
|
908
907
|
await summarize("File not found");
|
|
909
908
|
await exit(true);
|
|
@@ -922,9 +921,8 @@ let run = async (file, shouldSave = false, shouldExit = true) => {
|
|
|
922
921
|
try {
|
|
923
922
|
ymlObj = await yaml.load(yml);
|
|
924
923
|
} catch (e) {
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
console.log(`Invalid YAML: ${file}`);
|
|
924
|
+
logger.error("%s", e);
|
|
925
|
+
logger.error(`Invalid YAML: ${file}`);
|
|
928
926
|
|
|
929
927
|
await summarize("Invalid YAML");
|
|
930
928
|
await exit(true);
|
|
@@ -933,8 +931,7 @@ let run = async (file, shouldSave = false, shouldExit = true) => {
|
|
|
933
931
|
if (ymlObj.version) {
|
|
934
932
|
let valid = isValidVersion(ymlObj.version);
|
|
935
933
|
if (!valid) {
|
|
936
|
-
|
|
937
|
-
console.log(
|
|
934
|
+
logger.error(
|
|
938
935
|
`Version mismatch: ${file}. Trying to run a test with v${ymlObj.version} test when this package is v${package.version}.`,
|
|
939
936
|
);
|
|
940
937
|
|
|
@@ -946,8 +943,8 @@ let run = async (file, shouldSave = false, shouldExit = true) => {
|
|
|
946
943
|
executionHistory = [];
|
|
947
944
|
|
|
948
945
|
for (const step of ymlObj.steps) {
|
|
949
|
-
|
|
950
|
-
|
|
946
|
+
logger.info(``, null);
|
|
947
|
+
logger.info(chalk.yellow(`${step.prompt || "no prompt"}`), null);
|
|
951
948
|
|
|
952
949
|
executionHistory.push({
|
|
953
950
|
prompt: step.prompt,
|
|
@@ -958,8 +955,8 @@ let run = async (file, shouldSave = false, shouldExit = true) => {
|
|
|
958
955
|
${yaml.dump(step)}
|
|
959
956
|
\`\`\``;
|
|
960
957
|
|
|
961
|
-
|
|
962
|
-
|
|
958
|
+
logger.debug(markdown);
|
|
959
|
+
logger.debug("load calling actOnMarkdown");
|
|
963
960
|
|
|
964
961
|
lastPrompt = step.prompt;
|
|
965
962
|
await actOnMarkdown(markdown, 0, true);
|
|
@@ -995,7 +992,7 @@ const setTerminalApp = async (win) => {
|
|
|
995
992
|
const iffy = async (condition, then, otherwise, depth) => {
|
|
996
993
|
analytics.track("if", { condition });
|
|
997
994
|
|
|
998
|
-
|
|
995
|
+
logger.info(generator.jsonToManual({ command: "if", condition }));
|
|
999
996
|
|
|
1000
997
|
let response = await commands.assert(condition);
|
|
1001
998
|
|
|
@@ -1011,11 +1008,11 @@ const iffy = async (condition, then, otherwise, depth) => {
|
|
|
1011
1008
|
const embed = async (file, depth) => {
|
|
1012
1009
|
analytics.track("embed", { file });
|
|
1013
1010
|
|
|
1014
|
-
|
|
1011
|
+
logger.info(generator.jsonToManual({ command: "embed", file }));
|
|
1015
1012
|
|
|
1016
1013
|
depth = depth + 1;
|
|
1017
1014
|
|
|
1018
|
-
|
|
1015
|
+
logger.info(`${file} (start)`);
|
|
1019
1016
|
|
|
1020
1017
|
// get the current wowrking directory where this file is being executed
|
|
1021
1018
|
let cwd = process.cwd();
|
|
@@ -1041,17 +1038,17 @@ const embed = async (file, depth) => {
|
|
|
1041
1038
|
await executeCommands(step.commands, depth);
|
|
1042
1039
|
}
|
|
1043
1040
|
|
|
1044
|
-
|
|
1041
|
+
logger.info(`${file} (end)`);
|
|
1045
1042
|
};
|
|
1046
1043
|
|
|
1047
1044
|
const start = async () => {
|
|
1048
|
-
//
|
|
1045
|
+
// logger.info(await system.getPrimaryDisplay());
|
|
1049
1046
|
|
|
1050
1047
|
// @todo add-auth
|
|
1051
1048
|
// if (!process.env.DASHCAM_API_KEY) {
|
|
1052
|
-
// log
|
|
1053
|
-
// log
|
|
1054
|
-
// log
|
|
1049
|
+
// log('info', chalk.red(`You must supply an API key`), 'system')
|
|
1050
|
+
// log('info', `Supply your API key with the \`DASHCAM_API_KEY\` environment variable.`, 'system');
|
|
1051
|
+
// log('info', 'You can get a key in the Dashcam Discord server: https://discord.com/invite/cWDFW8DzPm', 'system')
|
|
1055
1052
|
// process.exit();
|
|
1056
1053
|
// }
|
|
1057
1054
|
|
|
@@ -1062,13 +1059,11 @@ const start = async () => {
|
|
|
1062
1059
|
process.platform === "darwin" &&
|
|
1063
1060
|
!macScreenPerms.hasScreenCapturePermission()
|
|
1064
1061
|
) {
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
"info",
|
|
1062
|
+
logger.info(chalk.red("Screen capture permissions not enabled."));
|
|
1063
|
+
logger.info(
|
|
1068
1064
|
"You must enable screen capture permissions for the application calling `testdriverai`.",
|
|
1069
1065
|
);
|
|
1070
|
-
|
|
1071
|
-
"info",
|
|
1066
|
+
logger.info(
|
|
1072
1067
|
"Read More: https://docs.testdriver.ai/faq/screen-recording-permissions-mac-only",
|
|
1073
1068
|
);
|
|
1074
1069
|
analytics.track("noMacPermissions");
|
|
@@ -1078,14 +1073,14 @@ const start = async () => {
|
|
|
1078
1073
|
if (thisCommand !== "run") {
|
|
1079
1074
|
speak("Howdy! I am TestDriver version " + package.version);
|
|
1080
1075
|
|
|
1081
|
-
|
|
1076
|
+
logger.info(
|
|
1082
1077
|
chalk.red("Warning!") +
|
|
1083
1078
|
chalk.dim(" TestDriver sends screenshots of the desktop to our API."),
|
|
1084
1079
|
);
|
|
1085
|
-
|
|
1080
|
+
logger.info(
|
|
1086
1081
|
chalk.dim("https://docs.testdriver.ai/security-and-privacy/agent"),
|
|
1087
1082
|
);
|
|
1088
|
-
|
|
1083
|
+
logger.info("");
|
|
1089
1084
|
}
|
|
1090
1085
|
|
|
1091
1086
|
analytics.track("command", { command: thisCommand, file: thisFile });
|
|
@@ -1103,14 +1098,14 @@ const start = async () => {
|
|
|
1103
1098
|
|
|
1104
1099
|
process.on("uncaughtException", async (err) => {
|
|
1105
1100
|
analytics.track("uncaughtException", { err });
|
|
1106
|
-
|
|
1101
|
+
logger.error("Uncaught Exception: %s", err);
|
|
1107
1102
|
// You might want to exit the process after handling the error
|
|
1108
1103
|
await exit(true);
|
|
1109
1104
|
});
|
|
1110
1105
|
|
|
1111
1106
|
process.on("unhandledRejection", async (reason, promise) => {
|
|
1112
1107
|
analytics.track("unhandledRejection", { reason, promise });
|
|
1113
|
-
|
|
1108
|
+
logger.error("Unhandled Rejection at: %s, reason: %s", promise, reason);
|
|
1114
1109
|
// Optionally, you might want to exit the process
|
|
1115
1110
|
await exit(true);
|
|
1116
1111
|
});
|
package/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
const config = require("./lib/config.js");
|
|
3
3
|
const system = require("./lib/system.js");
|
|
4
4
|
const { emitter, events } = require("./lib/events.js");
|
|
5
|
+
const { logger } = require("./lib/logger.js");
|
|
5
6
|
|
|
6
7
|
(async () => {
|
|
7
8
|
|
|
@@ -40,7 +41,7 @@ const { emitter, events } = require("./lib/events.js");
|
|
|
40
41
|
agent.start();
|
|
41
42
|
})
|
|
42
43
|
.catch((err) => {
|
|
43
|
-
|
|
44
|
+
logger.error("%s", err);
|
|
44
45
|
process.exit(1);
|
|
45
46
|
});
|
|
46
47
|
}
|