testdriverai 6.1.0 → 6.1.1-canary.613bfa3.0
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/events.js +1 -10
- package/agent/index.js +33 -33
- package/agent/lib/commander.js +16 -16
- package/agent/lib/commands.js +7 -7
- package/agent/lib/debugger-server.js +0 -5
- package/agent/lib/sandbox.js +1 -1
- package/agent/lib/source-mapper.js +1 -1
- package/docs/apps/tauri-apps.mdx +413 -0
- package/docs/docs.json +33 -28
- package/docs/getting-started/playwright.mdx +338 -0
- package/docs/getting-started/vscode.mdx +8 -3
- package/docs/styles.css +10 -1
- package/interfaces/cli/lib/base.js +8 -1
- package/interfaces/cli/utils/factory.js +7 -16
- package/interfaces/logger.js +4 -4
- package/package.json +3 -5
- package/.cursor/rules/trigger.basic.mdc +0 -190
- package/.github/instructions/trigger-basic.instructions.md +0 -188
- package/CLAUDE.md +0 -188
- package/index.html +0 -147
- package/static-analysis.datadog.yml +0 -10
- package/testdriver/examples/playwright/postrun.yaml +0 -44
- package/testdriver/examples/playwright/provision.yaml +0 -43
- package/testdriver/generate/test-locked-out-user-login.yaml +0 -37
- package/testdriver/generate/test-standard-user-login.yaml +0 -37
- package/testdriver/generate/test-successful-logout.yaml +0 -36
package/agent/events.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const { EventEmitter2 } = require("eventemitter2");
|
|
2
|
-
const { censorSensitiveDataDeep } = require("./lib/censorship");
|
|
3
2
|
|
|
4
3
|
// Factory function to create a new emitter instance with censoring middleware
|
|
5
4
|
const createEmitter = () => {
|
|
@@ -13,14 +12,6 @@ const createEmitter = () => {
|
|
|
13
12
|
ignoreErrors: false,
|
|
14
13
|
});
|
|
15
14
|
|
|
16
|
-
// Override emit to censor sensitive data before emitting
|
|
17
|
-
const originalEmit = emitter.emit.bind(emitter);
|
|
18
|
-
emitter.emit = function (event, ...args) {
|
|
19
|
-
// Censor all arguments passed to emit
|
|
20
|
-
const censoredArgs = args.map(censorSensitiveDataDeep);
|
|
21
|
-
return originalEmit(event, ...censoredArgs);
|
|
22
|
-
};
|
|
23
|
-
|
|
24
15
|
return emitter;
|
|
25
16
|
};
|
|
26
17
|
|
|
@@ -46,7 +37,7 @@ const events = {
|
|
|
46
37
|
status: "status",
|
|
47
38
|
log: {
|
|
48
39
|
markdown: {
|
|
49
|
-
static: "log:markdown
|
|
40
|
+
static: "log:markdown",
|
|
50
41
|
start: "log:markdown:start",
|
|
51
42
|
chunk: "log:markdown:chunk",
|
|
52
43
|
end: "log:markdown:end",
|
package/agent/index.js
CHANGED
|
@@ -63,11 +63,11 @@ class TestDriverAgent extends EventEmitter2 {
|
|
|
63
63
|
// Derive properties from cliArgs
|
|
64
64
|
const flags = cliArgs.options || {};
|
|
65
65
|
const firstArg = cliArgs.args && cliArgs.args[0];
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
// All commands (run, edit, generate) use the same pattern:
|
|
68
68
|
// first argument is the main file to work with
|
|
69
69
|
this.thisFile = firstArg || this.config.TD_DEFAULT_TEST_FILE;
|
|
70
|
-
|
|
70
|
+
|
|
71
71
|
this.resultFile = flags.resultFile || null;
|
|
72
72
|
this.newSandbox = flags.newSandbox || false;
|
|
73
73
|
this.healMode = flags.healMode || flags.heal || false;
|
|
@@ -91,8 +91,6 @@ class TestDriverAgent extends EventEmitter2 {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
|
|
96
94
|
// Create parser instance with this agent's emitter
|
|
97
95
|
this.parser = createParser(this.emitter);
|
|
98
96
|
|
|
@@ -433,6 +431,7 @@ class TestDriverAgent extends EventEmitter2 {
|
|
|
433
431
|
|
|
434
432
|
// Log current execution position for debugging
|
|
435
433
|
if (this.sourceMapper.currentFileSourceMap) {
|
|
434
|
+
this.emitter.emit(events.log.log, "");
|
|
436
435
|
this.emitter.emit(
|
|
437
436
|
events.log.log,
|
|
438
437
|
theme.dim(`${this.sourceMapper.getCurrentPositionDescription()}`),
|
|
@@ -490,14 +489,13 @@ class TestDriverAgent extends EventEmitter2 {
|
|
|
490
489
|
sourcePosition: sourcePosition,
|
|
491
490
|
});
|
|
492
491
|
|
|
493
|
-
await this.haveAIResolveError(
|
|
492
|
+
return await this.haveAIResolveError(
|
|
494
493
|
error,
|
|
495
494
|
yaml.dump({ commands: [yml] }),
|
|
496
495
|
depth,
|
|
497
496
|
true,
|
|
498
497
|
shouldSave,
|
|
499
498
|
);
|
|
500
|
-
throw error;
|
|
501
499
|
}
|
|
502
500
|
}
|
|
503
501
|
|
|
@@ -894,9 +892,6 @@ commands:
|
|
|
894
892
|
// it will generate files that contain only "prompts"
|
|
895
893
|
// @todo revit the generate command
|
|
896
894
|
async generate(count = 1) {
|
|
897
|
-
|
|
898
|
-
console.log('generate being called with count:', count)
|
|
899
|
-
|
|
900
895
|
this.emitter.emit(events.log.debug, `generate called with count: ${count}`);
|
|
901
896
|
|
|
902
897
|
await this.runLifecycle("prerun");
|
|
@@ -914,12 +909,12 @@ commands:
|
|
|
914
909
|
let message = await this.sdk.req(
|
|
915
910
|
"generate",
|
|
916
911
|
{
|
|
917
|
-
prompt:
|
|
912
|
+
prompt: "make sure to do a spellcheck",
|
|
918
913
|
image,
|
|
919
914
|
mousePosition: mouse,
|
|
920
915
|
activeWindow: activeWindow,
|
|
921
916
|
count,
|
|
922
|
-
stream: false
|
|
917
|
+
stream: false,
|
|
923
918
|
},
|
|
924
919
|
(chunk) => {
|
|
925
920
|
if (chunk.type === "data") {
|
|
@@ -932,8 +927,6 @@ commands:
|
|
|
932
927
|
|
|
933
928
|
let testPrompts = await this.parser.findGenerativePrompts(message.data);
|
|
934
929
|
|
|
935
|
-
console.log(testPrompts)
|
|
936
|
-
|
|
937
930
|
// for each testPrompt
|
|
938
931
|
for (const testPrompt of testPrompts) {
|
|
939
932
|
// with the contents of the testPrompt
|
|
@@ -955,9 +948,9 @@ commands:
|
|
|
955
948
|
const generateDir = path.join(this.workingDir, "testdriver", "generate");
|
|
956
949
|
if (!fs.existsSync(generateDir)) {
|
|
957
950
|
fs.mkdirSync(generateDir);
|
|
958
|
-
console.log(
|
|
951
|
+
console.log("Created generate directory:", generateDir);
|
|
959
952
|
} else {
|
|
960
|
-
console.log(
|
|
953
|
+
console.log("Generate directory already exists:", generateDir);
|
|
961
954
|
}
|
|
962
955
|
|
|
963
956
|
let list = testPrompt.steps;
|
|
@@ -967,8 +960,7 @@ commands:
|
|
|
967
960
|
steps: list,
|
|
968
961
|
});
|
|
969
962
|
|
|
970
|
-
|
|
971
|
-
console.log('writing file', path1, contents)
|
|
963
|
+
this.emitter.emit(events.log.debug, `writing file ${path1} ${contents}`);
|
|
972
964
|
|
|
973
965
|
fs.writeFileSync(path1, contents);
|
|
974
966
|
}
|
|
@@ -1525,6 +1517,8 @@ ${regression}
|
|
|
1525
1517
|
}
|
|
1526
1518
|
|
|
1527
1519
|
async embed(file, depth, pushToHistory) {
|
|
1520
|
+
let inputFile = JSON.parse(JSON.stringify(file));
|
|
1521
|
+
|
|
1528
1522
|
this.analytics.track("embed", { file });
|
|
1529
1523
|
|
|
1530
1524
|
this.emitter.emit(
|
|
@@ -1534,7 +1528,7 @@ ${regression}
|
|
|
1534
1528
|
|
|
1535
1529
|
depth = depth + 1;
|
|
1536
1530
|
|
|
1537
|
-
this.emitter.emit(events.log.log, `${
|
|
1531
|
+
this.emitter.emit(events.log.log, `${inputFile} (start)`);
|
|
1538
1532
|
|
|
1539
1533
|
// Use the new helper method to resolve file paths relative to testdriver directory
|
|
1540
1534
|
const currentFilePath = this.sourceMapper.currentFilePath || this.thisFile;
|
|
@@ -1587,7 +1581,7 @@ ${regression}
|
|
|
1587
1581
|
this.sourceMapper.restoreContext(previousContext);
|
|
1588
1582
|
}
|
|
1589
1583
|
|
|
1590
|
-
this.emitter.emit(events.log.log, `${
|
|
1584
|
+
this.emitter.emit(events.log.log, `${inputFile} (end)`);
|
|
1591
1585
|
}
|
|
1592
1586
|
|
|
1593
1587
|
// Returns sandboxId to use (either from file if recent, or null)
|
|
@@ -1794,10 +1788,6 @@ ${regression}
|
|
|
1794
1788
|
// Start the debugger server as early as possible to ensure event listeners are attached
|
|
1795
1789
|
if (!debuggerStarted) {
|
|
1796
1790
|
debuggerStarted = true; // Prevent multiple starts, especially when running test in parallel
|
|
1797
|
-
this.emitter.emit(
|
|
1798
|
-
events.log.narration,
|
|
1799
|
-
theme.green(`Starting debugger server...`),
|
|
1800
|
-
);
|
|
1801
1791
|
debuggerProcess = await createDebuggerProcess(
|
|
1802
1792
|
this.config,
|
|
1803
1793
|
this.emitter,
|
|
@@ -1805,6 +1795,7 @@ ${regression}
|
|
|
1805
1795
|
}
|
|
1806
1796
|
this.debuggerUrl = debuggerProcess.url || null; // Store the debugger URL
|
|
1807
1797
|
this.emitter.emit(events.log.log, `This is beta software!`);
|
|
1798
|
+
this.emitter.emit(events.log.log, ``);
|
|
1808
1799
|
this.emitter.emit(
|
|
1809
1800
|
events.log.log,
|
|
1810
1801
|
theme.yellow(`Join our Discord for help`),
|
|
@@ -1813,6 +1804,7 @@ ${regression}
|
|
|
1813
1804
|
events.log.log,
|
|
1814
1805
|
`https://discord.com/invite/cWDFW8DzPm`,
|
|
1815
1806
|
);
|
|
1807
|
+
this.emitter.emit(events.log.log, ``);
|
|
1816
1808
|
|
|
1817
1809
|
// make testdriver directory if it doesn't exist
|
|
1818
1810
|
let testdriverFolder = path.join(this.workingDir);
|
|
@@ -1826,7 +1818,10 @@ ${regression}
|
|
|
1826
1818
|
}
|
|
1827
1819
|
|
|
1828
1820
|
// if the directory for thisFile doesn't exist, create it
|
|
1829
|
-
if (
|
|
1821
|
+
if (
|
|
1822
|
+
this.cliArgs.command !== "sandbox" &&
|
|
1823
|
+
this.cliArgs.command !== "generate"
|
|
1824
|
+
) {
|
|
1830
1825
|
const dir = path.dirname(this.thisFile);
|
|
1831
1826
|
if (!fs.existsSync(dir)) {
|
|
1832
1827
|
fs.mkdirSync(dir, { recursive: true });
|
|
@@ -1851,7 +1846,10 @@ ${regression}
|
|
|
1851
1846
|
await this.sdk.auth();
|
|
1852
1847
|
}
|
|
1853
1848
|
|
|
1854
|
-
if (
|
|
1849
|
+
if (
|
|
1850
|
+
this.cliArgs.command !== "sandbox" &&
|
|
1851
|
+
this.cliArgs.command !== "generate"
|
|
1852
|
+
) {
|
|
1855
1853
|
this.emitter.emit(
|
|
1856
1854
|
events.log.log,
|
|
1857
1855
|
theme.dim(`Working on ${this.thisFile}`),
|
|
@@ -2045,21 +2043,23 @@ Please check your network connection, TD_API_KEY, or the service status.`,
|
|
|
2045
2043
|
}
|
|
2046
2044
|
|
|
2047
2045
|
async runLifecycle(lifecycleName) {
|
|
2048
|
-
|
|
2049
|
-
console.log("Running lifecycle:", lifecycleName);
|
|
2050
|
-
|
|
2051
2046
|
// Use the current file path from sourceMapper to find the lifecycle directory
|
|
2052
2047
|
// If sourceMapper doesn't have a current file, use thisFile which should be the file being run
|
|
2053
2048
|
let currentFilePath = this.sourceMapper.currentFilePath || this.thisFile;
|
|
2054
2049
|
|
|
2055
|
-
|
|
2056
|
-
|
|
2050
|
+
this.emitter.emit(events.log.log, ``);
|
|
2051
|
+
this.emitter.emit(events.log.log, "Running lifecycle: " + lifecycleName);
|
|
2052
|
+
|
|
2057
2053
|
// If we still don't have a currentFilePath, fall back to the default testdriver directory
|
|
2058
2054
|
if (!currentFilePath) {
|
|
2059
|
-
currentFilePath = path.join(
|
|
2055
|
+
currentFilePath = path.join(
|
|
2056
|
+
this.workingDir,
|
|
2057
|
+
"testdriver",
|
|
2058
|
+
"testdriver.yaml",
|
|
2059
|
+
);
|
|
2060
2060
|
console.log("No currentFilePath found, using fallback:", currentFilePath);
|
|
2061
2061
|
}
|
|
2062
|
-
|
|
2062
|
+
|
|
2063
2063
|
// Ensure we have an absolute path
|
|
2064
2064
|
if (currentFilePath && !path.isAbsolute(currentFilePath)) {
|
|
2065
2065
|
currentFilePath = path.resolve(this.workingDir, currentFilePath);
|
|
@@ -2097,7 +2097,7 @@ Please check your network connection, TD_API_KEY, or the service status.`,
|
|
|
2097
2097
|
}
|
|
2098
2098
|
}
|
|
2099
2099
|
|
|
2100
|
-
|
|
2100
|
+
this.emitter.emit(events.log.log, lifecycleFile);
|
|
2101
2101
|
|
|
2102
2102
|
if (lifecycleFile) {
|
|
2103
2103
|
// Store current source mapping state before running lifecycle file
|
package/agent/lib/commander.js
CHANGED
|
@@ -80,21 +80,21 @@ commands:
|
|
|
80
80
|
// this will actually interpret the command and execute it
|
|
81
81
|
switch (object.command) {
|
|
82
82
|
case "type":
|
|
83
|
-
emitter.emit(events.log.narration, `typing ${object.text}`);
|
|
84
83
|
emitter.emit(events.log.log, generator.jsonToManual(object));
|
|
84
|
+
emitter.emit(events.log.narration, `typing ${object.text}`);
|
|
85
85
|
response = await commands.type(object.text, object.delay);
|
|
86
86
|
break;
|
|
87
87
|
case "press-keys":
|
|
88
|
+
emitter.emit(events.log.log, generator.jsonToManual(object));
|
|
88
89
|
emitter.emit(
|
|
89
90
|
events.log.narration,
|
|
90
|
-
`pressing keys ${object.keys.join(",")}`,
|
|
91
|
+
`pressing keys: ${Array.isArray(object.keys) ? object.keys.join(", ") : object.keys}`,
|
|
91
92
|
);
|
|
92
|
-
emitter.emit(events.log.log, generator.jsonToManual(object));
|
|
93
93
|
response = await commands["press-keys"](object.keys);
|
|
94
94
|
break;
|
|
95
95
|
case "scroll":
|
|
96
|
-
emitter.emit(events.log.narration, `scrolling ${object.direction}`);
|
|
97
96
|
emitter.emit(events.log.log, generator.jsonToManual(object));
|
|
97
|
+
emitter.emit(events.log.narration, `scrolling ${object.direction}`);
|
|
98
98
|
response = await commands.scroll(
|
|
99
99
|
object.direction,
|
|
100
100
|
object.amount,
|
|
@@ -102,21 +102,21 @@ commands:
|
|
|
102
102
|
);
|
|
103
103
|
break;
|
|
104
104
|
case "wait":
|
|
105
|
+
emitter.emit(events.log.log, generator.jsonToManual(object));
|
|
105
106
|
emitter.emit(
|
|
106
107
|
events.log.narration,
|
|
107
108
|
`waiting ${object.timeout} seconds`,
|
|
108
109
|
);
|
|
109
|
-
emitter.emit(events.log.log, generator.jsonToManual(object));
|
|
110
110
|
response = await commands.wait(object.timeout);
|
|
111
111
|
break;
|
|
112
112
|
case "click":
|
|
113
|
-
emitter.emit(events.log.narration, `${object.action}`);
|
|
114
113
|
emitter.emit(events.log.log, generator.jsonToManual(object));
|
|
114
|
+
emitter.emit(events.log.narration, `${object.action}`);
|
|
115
115
|
response = await commands["click"](object.x, object.y, object.action);
|
|
116
116
|
break;
|
|
117
117
|
case "hover":
|
|
118
|
-
emitter.emit(events.log.narration, `moving mouse`);
|
|
119
118
|
emitter.emit(events.log.log, generator.jsonToManual(object));
|
|
119
|
+
emitter.emit(events.log.narration, `moving mouse`);
|
|
120
120
|
response = await commands["hover"](object.x, object.y);
|
|
121
121
|
break;
|
|
122
122
|
case "drag":
|
|
@@ -124,11 +124,11 @@ commands:
|
|
|
124
124
|
response = await commands["drag"](object.x, object.y);
|
|
125
125
|
break;
|
|
126
126
|
case "hover-text":
|
|
127
|
+
emitter.emit(events.log.log, generator.jsonToManual(object));
|
|
127
128
|
emitter.emit(
|
|
128
129
|
events.log.narration,
|
|
129
130
|
`searching for ${object.description}`,
|
|
130
131
|
);
|
|
131
|
-
emitter.emit(events.log.log, generator.jsonToManual(object));
|
|
132
132
|
response = await commands["hover-text"](
|
|
133
133
|
object.text,
|
|
134
134
|
object.description,
|
|
@@ -138,11 +138,11 @@ commands:
|
|
|
138
138
|
);
|
|
139
139
|
break;
|
|
140
140
|
case "hover-image":
|
|
141
|
+
emitter.emit(events.log.log, generator.jsonToManual(object));
|
|
141
142
|
emitter.emit(
|
|
142
143
|
events.log.narration,
|
|
143
144
|
`searching for image of ${object.description}`,
|
|
144
145
|
);
|
|
145
|
-
emitter.emit(events.log.log, generator.jsonToManual(object));
|
|
146
146
|
response = await commands["hover-image"](
|
|
147
147
|
object.description,
|
|
148
148
|
object.action,
|
|
@@ -157,19 +157,19 @@ commands:
|
|
|
157
157
|
response = await commands["match-image"](object.path, object.action);
|
|
158
158
|
break;
|
|
159
159
|
case "wait-for-image":
|
|
160
|
+
emitter.emit(events.log.log, generator.jsonToManual(object));
|
|
160
161
|
emitter.emit(
|
|
161
162
|
events.log.narration,
|
|
162
163
|
`waiting for ${object.description}`,
|
|
163
164
|
);
|
|
164
|
-
emitter.emit(events.log.log, generator.jsonToManual(object));
|
|
165
165
|
response = await commands["wait-for-image"](
|
|
166
166
|
object.description,
|
|
167
167
|
object.timeout,
|
|
168
168
|
);
|
|
169
169
|
break;
|
|
170
170
|
case "wait-for-text":
|
|
171
|
-
emitter.emit(events.log.narration, `waiting for ${object.text}`);
|
|
172
171
|
emitter.emit(events.log.log, generator.jsonToManual(object));
|
|
172
|
+
emitter.emit(events.log.narration, `waiting for ${object.text}`);
|
|
173
173
|
copy.text = "*****";
|
|
174
174
|
response = await commands["wait-for-text"](
|
|
175
175
|
object.text,
|
|
@@ -178,8 +178,8 @@ commands:
|
|
|
178
178
|
);
|
|
179
179
|
break;
|
|
180
180
|
case "scroll-until-text":
|
|
181
|
-
emitter.emit(events.log.narration, `scrolling until ${object.text}`);
|
|
182
181
|
emitter.emit(events.log.log, generator.jsonToManual(object));
|
|
182
|
+
emitter.emit(events.log.narration, `scrolling until ${object.text}`);
|
|
183
183
|
copy.text = "*****";
|
|
184
184
|
response = await commands["scroll-until-text"](
|
|
185
185
|
object.text,
|
|
@@ -191,8 +191,8 @@ commands:
|
|
|
191
191
|
break;
|
|
192
192
|
case "scroll-until-image": {
|
|
193
193
|
const needle = object.description || object.path;
|
|
194
|
-
emitter.emit(events.log.narration, `scrolling until ${needle}`);
|
|
195
194
|
emitter.emit(events.log.log, generator.jsonToManual(object));
|
|
195
|
+
emitter.emit(events.log.narration, `scrolling until ${needle}`);
|
|
196
196
|
response = await commands["scroll-until-image"](
|
|
197
197
|
object.description,
|
|
198
198
|
object.direction,
|
|
@@ -203,8 +203,8 @@ commands:
|
|
|
203
203
|
break;
|
|
204
204
|
}
|
|
205
205
|
case "focus-application":
|
|
206
|
-
emitter.emit(events.log.narration, `focusing ${object.name}`);
|
|
207
206
|
emitter.emit(events.log.log, generator.jsonToManual(object));
|
|
207
|
+
emitter.emit(events.log.narration, `focusing ${object.name}`);
|
|
208
208
|
response = await commands["focus-application"](object.name);
|
|
209
209
|
break;
|
|
210
210
|
case "remember": {
|
|
@@ -215,12 +215,12 @@ commands:
|
|
|
215
215
|
break;
|
|
216
216
|
}
|
|
217
217
|
case "assert":
|
|
218
|
-
emitter.emit(events.log.narration, `asserting ${object.expect}`);
|
|
219
218
|
emitter.emit(events.log.log, generator.jsonToManual(object));
|
|
219
|
+
emitter.emit(events.log.narration, `asserting ${object.expect}`);
|
|
220
220
|
response = await commands.assert(object.expect, object.async);
|
|
221
|
+
|
|
221
222
|
break;
|
|
222
223
|
case "exec":
|
|
223
|
-
emitter.emit(events.log.narration, `exec`);
|
|
224
224
|
emitter.emit(
|
|
225
225
|
events.log.log,
|
|
226
226
|
generator.jsonToManual({
|
package/agent/lib/commands.js
CHANGED
|
@@ -176,7 +176,7 @@ const createCommands = (
|
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
const handleAssertResponse = (response) => {
|
|
179
|
-
emitter.emit(events.log.
|
|
179
|
+
emitter.emit(events.log.log, response);
|
|
180
180
|
|
|
181
181
|
if (response.indexOf("The task passed") > -1) {
|
|
182
182
|
return true;
|
|
@@ -727,14 +727,14 @@ const createCommands = (
|
|
|
727
727
|
`Command failed with exit code ${result.out.returncode}: ${result.out.stderr}`,
|
|
728
728
|
);
|
|
729
729
|
} else {
|
|
730
|
-
if (!silent) {
|
|
731
|
-
emitter.emit(events.log.log, theme.dim(`
|
|
730
|
+
if (!silent && result.out?.stdout) {
|
|
731
|
+
emitter.emit(events.log.log, theme.dim(`stdout:`), true);
|
|
732
732
|
emitter.emit(events.log.log, `${result.out.stdout}`, true);
|
|
733
|
+
}
|
|
733
734
|
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
}
|
|
735
|
+
if (!silent && result.out.stderr) {
|
|
736
|
+
emitter.emit(events.log.log, theme.dim(`stderr:`), true);
|
|
737
|
+
emitter.emit(events.log.log, `${result.out.stderr}`, true);
|
|
738
738
|
}
|
|
739
739
|
|
|
740
740
|
return result.out?.stdout?.trim();
|
|
@@ -65,11 +65,6 @@ function createDebuggerServer(config = {}) {
|
|
|
65
65
|
|
|
66
66
|
ws.on("close", () => {
|
|
67
67
|
clients.delete(ws);
|
|
68
|
-
|
|
69
|
-
// If no clients connected, we can optionally shut down
|
|
70
|
-
if (clients.size === 0) {
|
|
71
|
-
console.log("No clients connected, keeping server alive");
|
|
72
|
-
}
|
|
73
68
|
});
|
|
74
69
|
|
|
75
70
|
ws.on("error", (error) => {
|
package/agent/lib/sandbox.js
CHANGED
|
@@ -23,7 +23,7 @@ const createSandbox = (emitter, analytics) => {
|
|
|
23
23
|
if (this.socket) {
|
|
24
24
|
this.messageId++;
|
|
25
25
|
message.requestId = `${this.uniqueId}-${this.messageId}`;
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
// Start timing for this message
|
|
28
28
|
const timingKey = `sandbox-${message.type}`;
|
|
29
29
|
marky.mark(timingKey);
|
|
@@ -263,7 +263,7 @@ class SourceMapper {
|
|
|
263
263
|
let description = `${fileName}:${(sourcePosition.step.startLine || 0) + 1}`;
|
|
264
264
|
|
|
265
265
|
if (sourcePosition.command) {
|
|
266
|
-
description += `:${(sourcePosition.command.startLine || 0) + 1}
|
|
266
|
+
description += `:${(sourcePosition.command.startLine || 0) + 1}`;
|
|
267
267
|
} else {
|
|
268
268
|
description += ` (step ${sourcePosition.step.stepIndex + 1})`;
|
|
269
269
|
}
|