codeloop-mcp-server 0.1.5 → 0.1.7
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/dist/auth/usage_tracker.d.ts +1 -1
- package/dist/auth/usage_tracker.d.ts.map +1 -1
- package/dist/auth/usage_tracker.js.map +1 -1
- package/dist/index.js +463 -14
- package/dist/index.js.map +1 -1
- package/dist/runners/app_logger.d.ts +10 -0
- package/dist/runners/app_logger.d.ts.map +1 -1
- package/dist/runners/app_logger.js +78 -5
- package/dist/runners/app_logger.js.map +1 -1
- package/dist/runners/browser_interaction.d.ts +27 -0
- package/dist/runners/browser_interaction.d.ts.map +1 -0
- package/dist/runners/browser_interaction.js +294 -0
- package/dist/runners/browser_interaction.js.map +1 -0
- package/dist/runners/maestro_generator.d.ts +11 -0
- package/dist/runners/maestro_generator.d.ts.map +1 -0
- package/dist/runners/maestro_generator.js +79 -0
- package/dist/runners/maestro_generator.js.map +1 -0
- package/dist/runners/screenshot.d.ts +1 -1
- package/dist/runners/screenshot.d.ts.map +1 -1
- package/dist/runners/screenshot.js +47 -2
- package/dist/runners/screenshot.js.map +1 -1
- package/dist/runners/video_recorder.d.ts +12 -1
- package/dist/runners/video_recorder.d.ts.map +1 -1
- package/dist/runners/video_recorder.js +33 -1
- package/dist/runners/video_recorder.js.map +1 -1
- package/dist/runners/video_validator.d.ts +16 -0
- package/dist/runners/video_validator.d.ts.map +1 -0
- package/dist/runners/video_validator.js +123 -0
- package/dist/runners/video_validator.js.map +1 -0
- package/dist/runners/win_accessibility.d.ts +12 -0
- package/dist/runners/win_accessibility.d.ts.map +1 -0
- package/dist/runners/win_accessibility.js +101 -0
- package/dist/runners/win_accessibility.js.map +1 -0
- package/dist/runners/window_manager.d.ts +26 -0
- package/dist/runners/window_manager.d.ts.map +1 -1
- package/dist/runners/window_manager.js +529 -0
- package/dist/runners/window_manager.js.map +1 -1
- package/dist/tools/gate_check.d.ts.map +1 -1
- package/dist/tools/gate_check.js +87 -4
- package/dist/tools/gate_check.js.map +1 -1
- package/dist/tools/interaction_replay.d.ts +6 -0
- package/dist/tools/interaction_replay.d.ts.map +1 -1
- package/dist/tools/interaction_replay.js +54 -0
- package/dist/tools/interaction_replay.js.map +1 -1
- package/dist/tools/verify.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { platform } from "os";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { mkdirSync, appendFileSync } from "fs";
|
|
4
|
+
import { runCommand } from "./base.js";
|
|
5
|
+
import { typeText, scrollAtPosition, sendHotkey } from "./window_manager.js";
|
|
6
|
+
let playwrightAvailable = null;
|
|
7
|
+
let activeBrowser = null;
|
|
8
|
+
let activePage = null;
|
|
9
|
+
let logPath = null;
|
|
10
|
+
let logStartTime = null;
|
|
11
|
+
async function isPlaywrightAvailable() {
|
|
12
|
+
if (playwrightAvailable !== null)
|
|
13
|
+
return playwrightAvailable;
|
|
14
|
+
try {
|
|
15
|
+
await import("playwright");
|
|
16
|
+
playwrightAvailable = true;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
playwrightAvailable = false;
|
|
20
|
+
}
|
|
21
|
+
return playwrightAvailable;
|
|
22
|
+
}
|
|
23
|
+
function timestampedLog(message) {
|
|
24
|
+
if (!logPath)
|
|
25
|
+
return;
|
|
26
|
+
const ts = new Date().toISOString();
|
|
27
|
+
try {
|
|
28
|
+
appendFileSync(logPath, `[${ts}] ${message}\n`);
|
|
29
|
+
}
|
|
30
|
+
catch { /* best effort */ }
|
|
31
|
+
}
|
|
32
|
+
export async function launchBrowser(url, outputDir) {
|
|
33
|
+
if (outputDir) {
|
|
34
|
+
mkdirSync(outputDir, { recursive: true });
|
|
35
|
+
logPath = join(outputDir, `browser_log_${Date.now()}.txt`);
|
|
36
|
+
logStartTime = Date.now();
|
|
37
|
+
timestampedLog(`Browser session started — navigating to ${url}`);
|
|
38
|
+
}
|
|
39
|
+
if (await isPlaywrightAvailable()) {
|
|
40
|
+
try {
|
|
41
|
+
const pw = await import("playwright");
|
|
42
|
+
activeBrowser = await pw.chromium.launch({ headless: false });
|
|
43
|
+
const context = await activeBrowser.newContext();
|
|
44
|
+
activePage = await context.newPage();
|
|
45
|
+
activePage.on("console", (msg) => {
|
|
46
|
+
timestampedLog(`[console.${msg.type()}] ${msg.text()}`);
|
|
47
|
+
});
|
|
48
|
+
activePage.on("pageerror", (err) => {
|
|
49
|
+
timestampedLog(`[pageerror] ${err.message}`);
|
|
50
|
+
});
|
|
51
|
+
activePage.on("requestfailed", (req) => {
|
|
52
|
+
timestampedLog(`[request-failed] ${req.method()} ${req.url()} — ${req.failure()?.errorText}`);
|
|
53
|
+
});
|
|
54
|
+
activePage.on("response", (res) => {
|
|
55
|
+
if (res.status() >= 400) {
|
|
56
|
+
timestampedLog(`[http-error] ${res.status()} ${res.url()}`);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
await activePage.goto(url, { waitUntil: "domcontentloaded", timeout: 30000 });
|
|
60
|
+
return { launched: true, method: "playwright-headful" };
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
return { launched: false, method: "playwright-headful", error: String(err) };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const os = platform();
|
|
67
|
+
const openCmd = os === "darwin" ? "open" : os === "win32" ? "start" : "xdg-open";
|
|
68
|
+
await runCommand(openCmd, [url], process.cwd());
|
|
69
|
+
return { launched: true, method: `os-native-${openCmd}` };
|
|
70
|
+
}
|
|
71
|
+
export async function browserClick(selector) {
|
|
72
|
+
if (activePage) {
|
|
73
|
+
try {
|
|
74
|
+
await activePage.click(selector, { timeout: 5000 });
|
|
75
|
+
timestampedLog(`[interact] click "${selector}"`);
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
catch { /* fallthrough */ }
|
|
79
|
+
}
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
export async function browserDoubleClick(selector) {
|
|
83
|
+
if (activePage) {
|
|
84
|
+
try {
|
|
85
|
+
await activePage.dblclick(selector, { timeout: 5000 });
|
|
86
|
+
timestampedLog(`[interact] dblclick "${selector}"`);
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
catch { /* fallthrough */ }
|
|
90
|
+
}
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
export async function browserRightClick(selector) {
|
|
94
|
+
if (activePage) {
|
|
95
|
+
try {
|
|
96
|
+
await activePage.click(selector, { button: "right", timeout: 5000 });
|
|
97
|
+
timestampedLog(`[interact] right-click "${selector}"`);
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
catch { /* fallthrough */ }
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
export async function browserType(selector, text) {
|
|
105
|
+
if (activePage) {
|
|
106
|
+
try {
|
|
107
|
+
await activePage.fill(selector, text, { timeout: 5000 });
|
|
108
|
+
timestampedLog(`[interact] type "${selector}" → "${text.substring(0, 50)}"`);
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
catch { /* fallthrough */ }
|
|
112
|
+
}
|
|
113
|
+
return typeText(text);
|
|
114
|
+
}
|
|
115
|
+
export async function browserScroll(direction, amount = 300) {
|
|
116
|
+
if (activePage) {
|
|
117
|
+
try {
|
|
118
|
+
const deltaX = direction === "left" ? -amount : direction === "right" ? amount : 0;
|
|
119
|
+
const deltaY = direction === "up" ? -amount : direction === "down" ? amount : 0;
|
|
120
|
+
await activePage.mouse.wheel(deltaX, deltaY);
|
|
121
|
+
timestampedLog(`[interact] scroll ${direction} ${amount}`);
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
catch { /* fallthrough */ }
|
|
125
|
+
}
|
|
126
|
+
return scrollAtPosition(500, 400, direction, Math.round(amount / 100));
|
|
127
|
+
}
|
|
128
|
+
export async function browserHover(selector) {
|
|
129
|
+
if (activePage) {
|
|
130
|
+
try {
|
|
131
|
+
await activePage.hover(selector, { timeout: 5000 });
|
|
132
|
+
timestampedLog(`[interact] hover "${selector}"`);
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
catch { /* fallthrough */ }
|
|
136
|
+
}
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
export async function browserNavigate(url) {
|
|
140
|
+
if (activePage) {
|
|
141
|
+
try {
|
|
142
|
+
await activePage.goto(url, { waitUntil: "domcontentloaded", timeout: 30000 });
|
|
143
|
+
timestampedLog(`[interact] navigate "${url}"`);
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
catch { /* fallthrough */ }
|
|
147
|
+
}
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
export async function browserSelectOption(selector, value) {
|
|
151
|
+
if (activePage) {
|
|
152
|
+
try {
|
|
153
|
+
await activePage.selectOption(selector, value, { timeout: 5000 });
|
|
154
|
+
timestampedLog(`[interact] selectOption "${selector}" → "${value}"`);
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
catch { /* fallthrough */ }
|
|
158
|
+
}
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
export async function browserToggle(selector) {
|
|
162
|
+
if (activePage) {
|
|
163
|
+
try {
|
|
164
|
+
const checked = await activePage.isChecked(selector);
|
|
165
|
+
if (checked) {
|
|
166
|
+
await activePage.uncheck(selector, { timeout: 5000 });
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
await activePage.check(selector, { timeout: 5000 });
|
|
170
|
+
}
|
|
171
|
+
timestampedLog(`[interact] toggle "${selector}" → ${!checked}`);
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
catch { /* fallthrough */ }
|
|
175
|
+
}
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
export async function browserUploadFile(selector, filePath) {
|
|
179
|
+
if (activePage) {
|
|
180
|
+
try {
|
|
181
|
+
await activePage.setInputFiles(selector, filePath, { timeout: 5000 });
|
|
182
|
+
timestampedLog(`[interact] uploadFile "${selector}" → "${filePath}"`);
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
catch { /* fallthrough */ }
|
|
186
|
+
}
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
export async function browserTypeAndSubmit(selector, text) {
|
|
190
|
+
if (activePage) {
|
|
191
|
+
try {
|
|
192
|
+
await activePage.fill(selector, text, { timeout: 5000 });
|
|
193
|
+
await activePage.press(selector, "Enter");
|
|
194
|
+
timestampedLog(`[interact] typeAndSubmit "${selector}" → "${text.substring(0, 50)}"`);
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
catch { /* fallthrough */ }
|
|
198
|
+
}
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
export async function browserTypeAndTab(selector, text) {
|
|
202
|
+
if (activePage) {
|
|
203
|
+
try {
|
|
204
|
+
await activePage.fill(selector, text, { timeout: 5000 });
|
|
205
|
+
await activePage.press(selector, "Tab");
|
|
206
|
+
timestampedLog(`[interact] typeAndTab "${selector}" → "${text.substring(0, 50)}"`);
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
catch { /* fallthrough */ }
|
|
210
|
+
}
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
export async function browserFillForm(fields, submitSelector) {
|
|
214
|
+
if (!activePage)
|
|
215
|
+
return false;
|
|
216
|
+
try {
|
|
217
|
+
for (const field of fields) {
|
|
218
|
+
if (field.type === "select") {
|
|
219
|
+
await activePage.selectOption(field.selector, field.value, { timeout: 5000 });
|
|
220
|
+
}
|
|
221
|
+
else if (field.type === "checkbox" || field.type === "radio") {
|
|
222
|
+
const checked = await activePage.isChecked(field.selector);
|
|
223
|
+
if (!checked)
|
|
224
|
+
await activePage.check(field.selector, { timeout: 5000 });
|
|
225
|
+
}
|
|
226
|
+
else if (field.type === "file") {
|
|
227
|
+
await activePage.setInputFiles(field.selector, field.value, { timeout: 5000 });
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
await activePage.fill(field.selector, field.value, { timeout: 5000 });
|
|
231
|
+
}
|
|
232
|
+
timestampedLog(`[interact] fillField "${field.selector}" → "${field.value.substring(0, 30)}"`);
|
|
233
|
+
}
|
|
234
|
+
if (submitSelector) {
|
|
235
|
+
await activePage.click(submitSelector, { timeout: 5000 });
|
|
236
|
+
timestampedLog(`[interact] submitForm "${submitSelector}"`);
|
|
237
|
+
}
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
export async function browserDragDrop(sourceSelector, targetSelector) {
|
|
245
|
+
if (activePage) {
|
|
246
|
+
try {
|
|
247
|
+
await activePage.dragAndDrop(sourceSelector, targetSelector);
|
|
248
|
+
timestampedLog(`[interact] dragDrop "${sourceSelector}" → "${targetSelector}"`);
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
catch { /* fallthrough */ }
|
|
252
|
+
}
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
export async function browserHotkey(combo) {
|
|
256
|
+
if (activePage) {
|
|
257
|
+
try {
|
|
258
|
+
const parts = combo.split("+").map(s => s.trim());
|
|
259
|
+
const pwCombo = parts.map(p => {
|
|
260
|
+
if (p === "cmd" || p === "meta")
|
|
261
|
+
return "Meta";
|
|
262
|
+
if (p === "ctrl")
|
|
263
|
+
return "Control";
|
|
264
|
+
if (p === "alt")
|
|
265
|
+
return "Alt";
|
|
266
|
+
if (p === "shift")
|
|
267
|
+
return "Shift";
|
|
268
|
+
return p.length === 1 ? p : p.charAt(0).toUpperCase() + p.slice(1);
|
|
269
|
+
}).join("+");
|
|
270
|
+
await activePage.keyboard.press(pwCombo);
|
|
271
|
+
timestampedLog(`[interact] hotkey "${combo}"`);
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
catch { /* fallthrough */ }
|
|
275
|
+
}
|
|
276
|
+
return sendHotkey(combo);
|
|
277
|
+
}
|
|
278
|
+
export function getBrowserLogPath() {
|
|
279
|
+
return logPath;
|
|
280
|
+
}
|
|
281
|
+
export async function closeBrowser() {
|
|
282
|
+
if (activeBrowser) {
|
|
283
|
+
timestampedLog("Browser session ended");
|
|
284
|
+
try {
|
|
285
|
+
await activeBrowser.close();
|
|
286
|
+
}
|
|
287
|
+
catch { /* ignore */ }
|
|
288
|
+
activeBrowser = null;
|
|
289
|
+
activePage = null;
|
|
290
|
+
}
|
|
291
|
+
logPath = null;
|
|
292
|
+
logStartTime = null;
|
|
293
|
+
}
|
|
294
|
+
//# sourceMappingURL=browser_interaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser_interaction.js","sourceRoot":"","sources":["../../src/runners/browser_interaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare function generateMaestroFlow(steps: string[], cwd: string): Promise<{
|
|
2
|
+
flowPath: string;
|
|
3
|
+
} | {
|
|
4
|
+
error: string;
|
|
5
|
+
}>;
|
|
6
|
+
export declare function runGeneratedFlow(flowPath: string, cwd: string): Promise<{
|
|
7
|
+
success: boolean;
|
|
8
|
+
output: string;
|
|
9
|
+
error?: string;
|
|
10
|
+
}>;
|
|
11
|
+
//# sourceMappingURL=maestro_generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maestro_generator.d.ts","sourceRoot":"","sources":["../../src/runners/maestro_generator.ts"],"names":[],"mappings":"AAIA,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,MAAM,EAAE,EACf,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAYnD;AAgDD,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAe/D"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { writeFileSync, mkdirSync, existsSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { checkToolAvailable, runCommand } from "./base.js";
|
|
4
|
+
export async function generateMaestroFlow(steps, cwd) {
|
|
5
|
+
const maestroDir = join(cwd, ".maestro");
|
|
6
|
+
mkdirSync(maestroDir, { recursive: true });
|
|
7
|
+
const yamlLines = ["appId: ${APP_ID}", "---"];
|
|
8
|
+
for (const step of steps) {
|
|
9
|
+
yamlLines.push(stepToYaml(step));
|
|
10
|
+
}
|
|
11
|
+
const flowPath = join(maestroDir, `codeloop_generated_${Date.now()}.yaml`);
|
|
12
|
+
writeFileSync(flowPath, yamlLines.join("\n") + "\n");
|
|
13
|
+
return { flowPath };
|
|
14
|
+
}
|
|
15
|
+
function stepToYaml(step) {
|
|
16
|
+
const lower = step.toLowerCase().trim();
|
|
17
|
+
const tapMatch = lower.match(/^tap\s+(\d+)\s+(\d+)$/);
|
|
18
|
+
if (tapMatch)
|
|
19
|
+
return `- tapOn:\n point: "${tapMatch[1]},${tapMatch[2]}"`;
|
|
20
|
+
const tapTextMatch = step.match(/^tap\s+"(.+)"$/i) || step.match(/^tap\s+on\s+"(.+)"$/i);
|
|
21
|
+
if (tapTextMatch)
|
|
22
|
+
return `- tapOn: "${tapTextMatch[1]}"`;
|
|
23
|
+
const typeMatch = step.match(/^type\s+"(.+)"$/i) || step.match(/^type\s+'(.+)'$/i);
|
|
24
|
+
if (typeMatch)
|
|
25
|
+
return `- inputText: "${typeMatch[1]}"`;
|
|
26
|
+
if (lower === "swipe up" || lower === "scroll down")
|
|
27
|
+
return "- scroll";
|
|
28
|
+
if (lower === "swipe down" || lower === "scroll up")
|
|
29
|
+
return "- scroll:\n direction: UP";
|
|
30
|
+
if (lower === "swipe left")
|
|
31
|
+
return "- swipe:\n direction: LEFT\n duration: 400";
|
|
32
|
+
if (lower === "swipe right")
|
|
33
|
+
return "- swipe:\n direction: RIGHT\n duration: 400";
|
|
34
|
+
if (lower === "back" || lower === "press back")
|
|
35
|
+
return "- pressKey: back";
|
|
36
|
+
if (lower === "home" || lower === "press home")
|
|
37
|
+
return "- pressKey: home";
|
|
38
|
+
if (lower === "enter" || lower === "press enter")
|
|
39
|
+
return "- pressKey: enter";
|
|
40
|
+
const waitMatch = lower.match(/^wait\s+(\d+)$/);
|
|
41
|
+
if (waitMatch)
|
|
42
|
+
return `- waitForAnimationToEnd:\n timeout: ${waitMatch[1]}`;
|
|
43
|
+
const assertMatch = step.match(/^assert\s+visible\s+"(.+)"$/i);
|
|
44
|
+
if (assertMatch)
|
|
45
|
+
return `- assertVisible: "${assertMatch[1]}"`;
|
|
46
|
+
const assertNotMatch = step.match(/^assert\s+not\s+visible\s+"(.+)"$/i);
|
|
47
|
+
if (assertNotMatch)
|
|
48
|
+
return `- assertNotVisible: "${assertNotMatch[1]}"`;
|
|
49
|
+
const launchMatch = step.match(/^launch\s+(.+)$/i);
|
|
50
|
+
if (launchMatch)
|
|
51
|
+
return `- launchApp:\n appId: "${launchMatch[1].trim()}"`;
|
|
52
|
+
if (lower === "clear state" || lower === "clear data")
|
|
53
|
+
return "- clearState";
|
|
54
|
+
if (lower === "clear keychain")
|
|
55
|
+
return "- clearKeychain";
|
|
56
|
+
if (lower === "take screenshot")
|
|
57
|
+
return "- takeScreenshot: codeloop_screenshot";
|
|
58
|
+
if (lower === "hide keyboard" || lower === "dismiss keyboard")
|
|
59
|
+
return "- hideKeyboard";
|
|
60
|
+
const longPressMatch = step.match(/^long\s*press\s+"(.+)"$/i);
|
|
61
|
+
if (longPressMatch)
|
|
62
|
+
return `- longPressOn: "${longPressMatch[1]}"`;
|
|
63
|
+
return `# Unrecognized step: ${step}`;
|
|
64
|
+
}
|
|
65
|
+
export async function runGeneratedFlow(flowPath, cwd) {
|
|
66
|
+
if (!(await checkToolAvailable("maestro"))) {
|
|
67
|
+
return { success: false, output: "", error: "Maestro is not installed. Install with: curl -Ls https://get.maestro.mobile.dev | bash" };
|
|
68
|
+
}
|
|
69
|
+
if (!existsSync(flowPath)) {
|
|
70
|
+
return { success: false, output: "", error: `Flow file not found: ${flowPath}` };
|
|
71
|
+
}
|
|
72
|
+
const result = await runCommand("maestro", ["test", flowPath], cwd);
|
|
73
|
+
return {
|
|
74
|
+
success: result.exit_code === 0,
|
|
75
|
+
output: result.stdout + result.stderr,
|
|
76
|
+
error: result.exit_code !== 0 ? result.stderr : undefined,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=maestro_generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maestro_generator.js","sourceRoot":"","sources":["../../src/runners/maestro_generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,6 @@ export interface ScreenshotResult {
|
|
|
8
8
|
* Capture a screenshot. If appName is provided, brings the app to front,
|
|
9
9
|
* captures only that app's window, then restores the previous frontmost app.
|
|
10
10
|
*/
|
|
11
|
-
export declare function captureScreenshot(outputDir: string, label?: string, appName?: string): Promise<ScreenshotResult>;
|
|
11
|
+
export declare function captureScreenshot(outputDir: string, label?: string, appName?: string, targetType?: string): Promise<ScreenshotResult>;
|
|
12
12
|
export declare function listScreenshots(dir: string): string[];
|
|
13
13
|
//# sourceMappingURL=screenshot.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../src/runners/screenshot.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE,MAAiB,EACxB,OAAO,CAAC,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../src/runners/screenshot.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE,MAAiB,EACxB,OAAO,CAAC,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,gBAAgB,CAAC,CAmB3B;AAgOD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAMrD"}
|
|
@@ -7,10 +7,16 @@ import { findWindowId, bringAppToFront, restorePreviousApp } from "./window_mana
|
|
|
7
7
|
* Capture a screenshot. If appName is provided, brings the app to front,
|
|
8
8
|
* captures only that app's window, then restores the previous frontmost app.
|
|
9
9
|
*/
|
|
10
|
-
export async function captureScreenshot(outputDir, label = "screen", appName) {
|
|
10
|
+
export async function captureScreenshot(outputDir, label = "screen", appName, targetType) {
|
|
11
11
|
mkdirSync(outputDir, { recursive: true });
|
|
12
12
|
const outputPath = join(outputDir, `${label}_${Date.now()}.png`);
|
|
13
13
|
const os = platform();
|
|
14
|
+
if (targetType === "android_emulator") {
|
|
15
|
+
return captureAndroidEmulator(outputPath);
|
|
16
|
+
}
|
|
17
|
+
if (targetType === "ios_simulator") {
|
|
18
|
+
return captureiOSSimulator(outputPath);
|
|
19
|
+
}
|
|
14
20
|
if (os === "darwin") {
|
|
15
21
|
return captureMacOS(outputPath, appName);
|
|
16
22
|
}
|
|
@@ -21,19 +27,58 @@ export async function captureScreenshot(outputDir, label = "screen", appName) {
|
|
|
21
27
|
return captureLinux(outputPath, appName);
|
|
22
28
|
}
|
|
23
29
|
}
|
|
30
|
+
async function captureAndroidEmulator(outputPath) {
|
|
31
|
+
if (!(await checkToolAvailable("adb"))) {
|
|
32
|
+
return { captured: false, paths: [], method: "adb", error: "adb not found" };
|
|
33
|
+
}
|
|
34
|
+
const result = await runCommand("adb", ["exec-out", "screencap", "-p"], process.cwd());
|
|
35
|
+
if (result.exit_code === 0) {
|
|
36
|
+
try {
|
|
37
|
+
const { writeFileSync: wf } = await import("fs");
|
|
38
|
+
wf(outputPath, Buffer.from(result.stdout, "binary"));
|
|
39
|
+
if (existsSync(outputPath)) {
|
|
40
|
+
return { captured: true, paths: [outputPath], method: "adb exec-out screencap" };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch { /* fallthrough */ }
|
|
44
|
+
}
|
|
45
|
+
// Fallback: use adb shell screencap + pull
|
|
46
|
+
await runCommand("adb", ["shell", "screencap", "-p", "/sdcard/codeloop_ss.png"], process.cwd());
|
|
47
|
+
const pullResult = await runCommand("adb", ["pull", "/sdcard/codeloop_ss.png", outputPath], process.cwd());
|
|
48
|
+
await runCommand("adb", ["shell", "rm", "/sdcard/codeloop_ss.png"], process.cwd());
|
|
49
|
+
if (pullResult.exit_code === 0 && existsSync(outputPath)) {
|
|
50
|
+
return { captured: true, paths: [outputPath], method: "adb shell screencap + pull" };
|
|
51
|
+
}
|
|
52
|
+
return { captured: false, paths: [], method: "adb", error: "Android screenshot capture failed" };
|
|
53
|
+
}
|
|
54
|
+
async function captureiOSSimulator(outputPath) {
|
|
55
|
+
if (!(await checkToolAvailable("xcrun"))) {
|
|
56
|
+
return { captured: false, paths: [], method: "xcrun", error: "xcrun not found" };
|
|
57
|
+
}
|
|
58
|
+
const result = await runCommand("xcrun", ["simctl", "io", "booted", "screenshot", outputPath], process.cwd());
|
|
59
|
+
if (result.exit_code === 0 && existsSync(outputPath)) {
|
|
60
|
+
return { captured: true, paths: [outputPath], method: "xcrun simctl io screenshot" };
|
|
61
|
+
}
|
|
62
|
+
return { captured: false, paths: [], method: "xcrun simctl", error: result.stderr || "iOS Simulator screenshot failed" };
|
|
63
|
+
}
|
|
24
64
|
async function captureMacOS(outputPath, appName) {
|
|
25
65
|
if (!(await checkToolAvailable("screencapture"))) {
|
|
26
66
|
return { captured: false, paths: [], method: "screencapture", error: "screencapture not found" };
|
|
27
67
|
}
|
|
28
68
|
if (appName) {
|
|
69
|
+
// Always bring the app to front first so it's not occluded by the IDE
|
|
70
|
+
const previousApp = await bringAppToFront(appName);
|
|
71
|
+
await new Promise(r => setTimeout(r, 500));
|
|
29
72
|
const windowId = await findWindowId(appName);
|
|
30
73
|
if (windowId) {
|
|
31
74
|
const wResult = await runCommand("screencapture", ["-l", windowId, "-x", "-o", outputPath], process.cwd());
|
|
32
75
|
if (wResult.exit_code === 0 && existsSync(outputPath)) {
|
|
76
|
+
if (previousApp && previousApp !== appName) {
|
|
77
|
+
await restorePreviousApp(previousApp);
|
|
78
|
+
}
|
|
33
79
|
return { captured: true, paths: [outputPath], method: `screencapture -l ${windowId} (window: ${appName})` };
|
|
34
80
|
}
|
|
35
81
|
}
|
|
36
|
-
const previousApp = await bringAppToFront(appName);
|
|
37
82
|
const fResult = await runCommand("screencapture", ["-x", "-o", outputPath], process.cwd());
|
|
38
83
|
const captured = fResult.exit_code === 0 && existsSync(outputPath);
|
|
39
84
|
if (previousApp && previousApp !== appName) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../src/runners/screenshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AASxF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,SAAiB,EACjB,QAAgB,QAAQ,EACxB,OAAgB;
|
|
1
|
+
{"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../src/runners/screenshot.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,7 +19,9 @@ export interface BackgroundRecordingHandle {
|
|
|
19
19
|
* Blocking video recording. Brings app to front, records for a fixed
|
|
20
20
|
* duration, then restores the previous frontmost app.
|
|
21
21
|
*/
|
|
22
|
-
export declare function recordVideo(outputDir: string, durationSeconds?: number, appName?: string): Promise<VideoRecordResult
|
|
22
|
+
export declare function recordVideo(outputDir: string, durationSeconds?: number, appName?: string): Promise<VideoRecordResult & {
|
|
23
|
+
log_path?: string;
|
|
24
|
+
}>;
|
|
23
25
|
/**
|
|
24
26
|
* Start recording in the background. Returns a handle immediately so the
|
|
25
27
|
* agent can interact with the app while recording is active.
|
|
@@ -44,4 +46,13 @@ export declare function stopBackgroundRecording(recordingId: string): Promise<Vi
|
|
|
44
46
|
}>;
|
|
45
47
|
/** List all active background recordings. */
|
|
46
48
|
export declare function listActiveRecordings(): string[];
|
|
49
|
+
/**
|
|
50
|
+
* Get the app name from any currently active recording.
|
|
51
|
+
* Used by codeloop_interact to bring the correct app to front before interaction.
|
|
52
|
+
*/
|
|
53
|
+
export declare function getActiveRecordingAppName(): string | null;
|
|
54
|
+
/**
|
|
55
|
+
* Get the target type from any currently active recording.
|
|
56
|
+
*/
|
|
57
|
+
export declare function getActiveRecordingTargetType(): string | null;
|
|
47
58
|
//# sourceMappingURL=video_recorder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"video_recorder.d.ts","sourceRoot":"","sources":["../../src/runners/video_recorder.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAgFtD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,yBAAyB;IACxC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,UAAU,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;CACtB;AAaD;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,EACjB,eAAe,GAAE,MAAW,EAC5B,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,iBAAiB,CAAC,
|
|
1
|
+
{"version":3,"file":"video_recorder.d.ts","sourceRoot":"","sources":["../../src/runners/video_recorder.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAgFtD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,yBAAyB;IACxC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,UAAU,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;CACtB;AAaD;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,EACjB,eAAe,GAAE,MAAW,EAC5B,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,iBAAiB,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAoCpD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,kBAAkB,GAAE,MAAY,EAChC,UAAU,GAAE,UAAsB,GACjC,OAAO,CAAC,yBAAyB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CA+LxD;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,iBAAiB,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAqFpD;AAED,6CAA6C;AAC7C,wBAAgB,oBAAoB,IAAI,MAAM,EAAE,CAE/C;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,GAAG,IAAI,CAKzD;AAED;;GAEG;AACH,wBAAgB,4BAA4B,IAAI,MAAM,GAAG,IAAI,CAK5D"}
|
|
@@ -89,6 +89,10 @@ export async function recordVideo(outputDir, durationSeconds = 10, appName) {
|
|
|
89
89
|
if (appName) {
|
|
90
90
|
previousApp = await bringAppToFront(appName);
|
|
91
91
|
}
|
|
92
|
+
// Start log capture alongside blocking recording
|
|
93
|
+
const logsDir = join(dirname(outputDir), "logs");
|
|
94
|
+
const logResult = await startLogCapture(logsDir, appName || "app", "desktop");
|
|
95
|
+
const logId = !("error" in logResult) ? logResult.logId : null;
|
|
92
96
|
let result;
|
|
93
97
|
if (os === "darwin") {
|
|
94
98
|
result = await recordMacOS(outputDir, durationSeconds, appName);
|
|
@@ -99,10 +103,17 @@ export async function recordVideo(outputDir, durationSeconds = 10, appName) {
|
|
|
99
103
|
else {
|
|
100
104
|
result = await recordLinux(outputDir, durationSeconds, appName);
|
|
101
105
|
}
|
|
106
|
+
// Stop log capture
|
|
107
|
+
let logPath;
|
|
108
|
+
if (logId) {
|
|
109
|
+
const lp = await stopLogCapture(logId);
|
|
110
|
+
if (lp)
|
|
111
|
+
logPath = lp;
|
|
112
|
+
}
|
|
102
113
|
if (previousApp && previousApp !== appName) {
|
|
103
114
|
await restorePreviousApp(previousApp);
|
|
104
115
|
}
|
|
105
|
-
return result;
|
|
116
|
+
return { ...result, log_path: logPath };
|
|
106
117
|
}
|
|
107
118
|
/**
|
|
108
119
|
* Start recording in the background. Returns a handle immediately so the
|
|
@@ -390,6 +401,27 @@ export async function stopBackgroundRecording(recordingId) {
|
|
|
390
401
|
export function listActiveRecordings() {
|
|
391
402
|
return Array.from(activeRecordings.keys());
|
|
392
403
|
}
|
|
404
|
+
/**
|
|
405
|
+
* Get the app name from any currently active recording.
|
|
406
|
+
* Used by codeloop_interact to bring the correct app to front before interaction.
|
|
407
|
+
*/
|
|
408
|
+
export function getActiveRecordingAppName() {
|
|
409
|
+
for (const rec of activeRecordings.values()) {
|
|
410
|
+
if (rec.appName)
|
|
411
|
+
return rec.appName;
|
|
412
|
+
}
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Get the target type from any currently active recording.
|
|
417
|
+
*/
|
|
418
|
+
export function getActiveRecordingTargetType() {
|
|
419
|
+
for (const rec of activeRecordings.values()) {
|
|
420
|
+
if (rec.targetType)
|
|
421
|
+
return rec.targetType;
|
|
422
|
+
}
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
393
425
|
async function recordMacOS(outputDir, durationSeconds, appName) {
|
|
394
426
|
if (!(await checkToolAvailable("screencapture"))) {
|
|
395
427
|
return { recorded: false, path: "", duration_seconds: durationSeconds, method: "screencapture", error: "screencapture not found" };
|