codeloop-mcp-server 0.1.4 → 0.1.6
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 +978 -40
- package/dist/index.js.map +1 -1
- package/dist/project-discovery.d.ts +17 -0
- package/dist/project-discovery.d.ts.map +1 -0
- package/dist/project-discovery.js +109 -0
- package/dist/project-discovery.js.map +1 -0
- package/dist/runners/app_logger.d.ts +41 -0
- package/dist/runners/app_logger.d.ts.map +1 -0
- package/dist/runners/app_logger.js +276 -0
- package/dist/runners/app_logger.js.map +1 -0
- package/dist/runners/base.d.ts.map +1 -1
- package/dist/runners/base.js +4 -2
- package/dist/runners/base.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/flutter.d.ts +1 -0
- package/dist/runners/flutter.d.ts.map +1 -1
- package/dist/runners/flutter.js +29 -0
- package/dist/runners/flutter.js.map +1 -1
- 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/platform_detect.d.ts +14 -0
- package/dist/runners/platform_detect.d.ts.map +1 -0
- package/dist/runners/platform_detect.js +102 -0
- package/dist/runners/platform_detect.js.map +1 -0
- package/dist/runners/screenshot.d.ts +3 -7
- package/dist/runners/screenshot.d.ts.map +1 -1
- package/dist/runners/screenshot.js +155 -28
- package/dist/runners/screenshot.js.map +1 -1
- package/dist/runners/video_recorder.d.ts +49 -0
- package/dist/runners/video_recorder.d.ts.map +1 -0
- package/dist/runners/video_recorder.js +489 -0
- package/dist/runners/video_recorder.js.map +1 -0
- 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 +81 -0
- package/dist/runners/window_manager.d.ts.map +1 -0
- package/dist/runners/window_manager.js +1010 -0
- package/dist/runners/window_manager.js.map +1 -0
- package/dist/tools/design_compare.d.ts +1 -1
- package/dist/tools/design_compare.d.ts.map +1 -1
- package/dist/tools/design_compare.js +1 -2
- package/dist/tools/design_compare.js.map +1 -1
- package/dist/tools/discover_screens.d.ts +3 -3
- package/dist/tools/discover_screens.d.ts.map +1 -1
- package/dist/tools/discover_screens.js +140 -157
- package/dist/tools/discover_screens.js.map +1 -1
- package/dist/tools/gate_check.d.ts.map +1 -1
- package/dist/tools/gate_check.js +100 -5
- package/dist/tools/gate_check.js.map +1 -1
- package/dist/tools/init-project.d.ts +15 -0
- package/dist/tools/init-project.d.ts.map +1 -0
- package/dist/tools/init-project.js +273 -0
- package/dist/tools/init-project.js.map +1 -0
- package/dist/tools/interaction_replay.d.ts +8 -1
- package/dist/tools/interaction_replay.d.ts.map +1 -1
- package/dist/tools/interaction_replay.js +78 -2
- package/dist/tools/interaction_replay.js.map +1 -1
- package/dist/tools/verify.d.ts.map +1 -1
- package/dist/tools/verify.js +204 -53
- package/dist/tools/verify.js.map +1 -1
- package/dist/tools/visual_review.d.ts +1 -1
- package/dist/tools/visual_review.d.ts.map +1 -1
- package/dist/tools/visual_review.js +1 -2
- package/dist/tools/visual_review.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { platform } from "os";
|
|
4
|
+
/**
|
|
5
|
+
* Auto-detect the target type for video recording and interaction based on
|
|
6
|
+
* the project structure and host OS.
|
|
7
|
+
*
|
|
8
|
+
* Detection priority:
|
|
9
|
+
* 1. Flutter project (pubspec.yaml) → check which platform is targeted
|
|
10
|
+
* 2. Xcode project (.xcodeproj) → ios_simulator (macOS only)
|
|
11
|
+
* 3. Android project (build.gradle) → android_emulator
|
|
12
|
+
* 4. Web project (package.json with web framework) → browser
|
|
13
|
+
* 5. Default → desktop
|
|
14
|
+
*/
|
|
15
|
+
export async function detectTargetType(cwd) {
|
|
16
|
+
// Flutter project detection
|
|
17
|
+
const pubspecPath = join(cwd, "pubspec.yaml");
|
|
18
|
+
if (existsSync(pubspecPath)) {
|
|
19
|
+
return detectFlutterTargetType(cwd, pubspecPath);
|
|
20
|
+
}
|
|
21
|
+
// Xcode project (native iOS/macOS)
|
|
22
|
+
if (hasFileWithExtension(cwd, ".xcodeproj") || hasFileWithExtension(cwd, ".xcworkspace")) {
|
|
23
|
+
const os = platform();
|
|
24
|
+
if (os === "darwin") {
|
|
25
|
+
// Check if it's a macOS app (look for macOS target) or iOS app
|
|
26
|
+
if (existsSync(join(cwd, "macos")))
|
|
27
|
+
return "desktop";
|
|
28
|
+
return "ios_simulator";
|
|
29
|
+
}
|
|
30
|
+
return "desktop";
|
|
31
|
+
}
|
|
32
|
+
// Android project (native)
|
|
33
|
+
if (existsSync(join(cwd, "build.gradle")) || existsSync(join(cwd, "build.gradle.kts")) ||
|
|
34
|
+
existsSync(join(cwd, "app", "build.gradle")) || existsSync(join(cwd, "app", "build.gradle.kts"))) {
|
|
35
|
+
return "android_emulator";
|
|
36
|
+
}
|
|
37
|
+
// Web project
|
|
38
|
+
const packageJsonPath = join(cwd, "package.json");
|
|
39
|
+
if (existsSync(packageJsonPath)) {
|
|
40
|
+
try {
|
|
41
|
+
const pkg = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
42
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
43
|
+
const webFrameworks = [
|
|
44
|
+
"react", "next", "vue", "nuxt", "svelte", "@sveltejs/kit",
|
|
45
|
+
"angular", "@angular/core", "gatsby", "remix", "astro", "vite",
|
|
46
|
+
];
|
|
47
|
+
if (webFrameworks.some(fw => fw in deps)) {
|
|
48
|
+
return "browser";
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch { /* ignore parse errors */ }
|
|
52
|
+
}
|
|
53
|
+
return "desktop";
|
|
54
|
+
}
|
|
55
|
+
function detectFlutterTargetType(cwd, _pubspecPath) {
|
|
56
|
+
const os = platform();
|
|
57
|
+
// Check which platform directories exist in the Flutter project
|
|
58
|
+
const hasAndroid = existsSync(join(cwd, "android"));
|
|
59
|
+
const hasIos = existsSync(join(cwd, "ios"));
|
|
60
|
+
const hasMacos = existsSync(join(cwd, "macos"));
|
|
61
|
+
const hasWindows = existsSync(join(cwd, "windows"));
|
|
62
|
+
const hasLinux = existsSync(join(cwd, "linux"));
|
|
63
|
+
const hasWeb = existsSync(join(cwd, "web"));
|
|
64
|
+
// Prefer the platform that matches the host OS
|
|
65
|
+
if (os === "darwin") {
|
|
66
|
+
if (hasMacos)
|
|
67
|
+
return "desktop";
|
|
68
|
+
if (hasIos)
|
|
69
|
+
return "ios_simulator";
|
|
70
|
+
if (hasWeb)
|
|
71
|
+
return "browser";
|
|
72
|
+
if (hasAndroid)
|
|
73
|
+
return "android_emulator";
|
|
74
|
+
}
|
|
75
|
+
else if (os === "win32") {
|
|
76
|
+
if (hasWindows)
|
|
77
|
+
return "desktop";
|
|
78
|
+
if (hasAndroid)
|
|
79
|
+
return "android_emulator";
|
|
80
|
+
if (hasWeb)
|
|
81
|
+
return "browser";
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
if (hasLinux)
|
|
85
|
+
return "desktop";
|
|
86
|
+
if (hasAndroid)
|
|
87
|
+
return "android_emulator";
|
|
88
|
+
if (hasWeb)
|
|
89
|
+
return "browser";
|
|
90
|
+
}
|
|
91
|
+
return "desktop";
|
|
92
|
+
}
|
|
93
|
+
function hasFileWithExtension(dir, ext) {
|
|
94
|
+
try {
|
|
95
|
+
const entries = readdirSync(dir);
|
|
96
|
+
return entries.some(e => e.endsWith(ext));
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=platform_detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform_detect.js","sourceRoot":"","sources":["../../src/runners/platform_detect.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,13 +5,9 @@ export interface ScreenshotResult {
|
|
|
5
5
|
error?: string;
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
|
-
* Capture a screenshot
|
|
9
|
-
*
|
|
10
|
-
* Falls back gracefully if no capture tool is available.
|
|
11
|
-
*/
|
|
12
|
-
export declare function captureScreenshot(outputDir: string, label?: string): Promise<ScreenshotResult>;
|
|
13
|
-
/**
|
|
14
|
-
* List all PNG screenshots already present in a directory.
|
|
8
|
+
* Capture a screenshot. If appName is provided, brings the app to front,
|
|
9
|
+
* captures only that app's window, then restores the previous frontmost app.
|
|
15
10
|
*/
|
|
11
|
+
export declare function captureScreenshot(outputDir: string, label?: string, appName?: string, targetType?: string): Promise<ScreenshotResult>;
|
|
16
12
|
export declare function listScreenshots(dir: string): string[];
|
|
17
13
|
//# sourceMappingURL=screenshot.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../src/runners/screenshot.ts"],"names":[],"mappings":"
|
|
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;AA0ND,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAMrD"}
|
|
@@ -1,32 +1,98 @@
|
|
|
1
|
-
import { existsSync, readdirSync } from "fs";
|
|
1
|
+
import { existsSync, readdirSync, mkdirSync } from "fs";
|
|
2
2
|
import { join } from "path";
|
|
3
3
|
import { platform } from "os";
|
|
4
4
|
import { runCommand, checkToolAvailable } from "./base.js";
|
|
5
|
+
import { findWindowId, bringAppToFront, restorePreviousApp } from "./window_manager.js";
|
|
5
6
|
/**
|
|
6
|
-
* Capture a screenshot
|
|
7
|
-
*
|
|
8
|
-
* Falls back gracefully if no capture tool is available.
|
|
7
|
+
* Capture a screenshot. If appName is provided, brings the app to front,
|
|
8
|
+
* captures only that app's window, then restores the previous frontmost app.
|
|
9
9
|
*/
|
|
10
|
-
export async function captureScreenshot(outputDir, label = "screen") {
|
|
10
|
+
export async function captureScreenshot(outputDir, label = "screen", appName, targetType) {
|
|
11
|
+
mkdirSync(outputDir, { recursive: true });
|
|
11
12
|
const outputPath = join(outputDir, `${label}_${Date.now()}.png`);
|
|
12
13
|
const os = platform();
|
|
14
|
+
if (targetType === "android_emulator") {
|
|
15
|
+
return captureAndroidEmulator(outputPath);
|
|
16
|
+
}
|
|
17
|
+
if (targetType === "ios_simulator") {
|
|
18
|
+
return captureiOSSimulator(outputPath);
|
|
19
|
+
}
|
|
13
20
|
if (os === "darwin") {
|
|
14
|
-
return captureMacOS(outputPath);
|
|
21
|
+
return captureMacOS(outputPath, appName);
|
|
15
22
|
}
|
|
16
23
|
else if (os === "win32") {
|
|
17
|
-
return captureWindows(outputPath);
|
|
24
|
+
return captureWindows(outputPath, appName);
|
|
18
25
|
}
|
|
19
26
|
else {
|
|
20
|
-
return captureLinux(outputPath);
|
|
27
|
+
return captureLinux(outputPath, appName);
|
|
28
|
+
}
|
|
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" };
|
|
21
51
|
}
|
|
52
|
+
return { captured: false, paths: [], method: "adb", error: "Android screenshot capture failed" };
|
|
22
53
|
}
|
|
23
|
-
async function
|
|
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
|
+
}
|
|
64
|
+
async function captureMacOS(outputPath, appName) {
|
|
24
65
|
if (!(await checkToolAvailable("screencapture"))) {
|
|
25
66
|
return { captured: false, paths: [], method: "screencapture", error: "screencapture not found" };
|
|
26
67
|
}
|
|
68
|
+
if (appName) {
|
|
69
|
+
const windowId = await findWindowId(appName);
|
|
70
|
+
if (windowId) {
|
|
71
|
+
const wResult = await runCommand("screencapture", ["-l", windowId, "-x", "-o", outputPath], process.cwd());
|
|
72
|
+
if (wResult.exit_code === 0 && existsSync(outputPath)) {
|
|
73
|
+
return { captured: true, paths: [outputPath], method: `screencapture -l ${windowId} (window: ${appName})` };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const previousApp = await bringAppToFront(appName);
|
|
77
|
+
const fResult = await runCommand("screencapture", ["-x", "-o", outputPath], process.cwd());
|
|
78
|
+
const captured = fResult.exit_code === 0 && existsSync(outputPath);
|
|
79
|
+
if (previousApp && previousApp !== appName) {
|
|
80
|
+
await restorePreviousApp(previousApp);
|
|
81
|
+
}
|
|
82
|
+
if (captured) {
|
|
83
|
+
const hint = windowId
|
|
84
|
+
? ". Tip: Grant Screen Recording permission (System Settings > Privacy & Security > Screen Recording) for window-only capture"
|
|
85
|
+
: "";
|
|
86
|
+
return { captured: true, paths: [outputPath], method: `screencapture (app "${appName}" brought to front, then restored)${hint}` };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
27
89
|
const result = await runCommand("screencapture", ["-x", "-o", outputPath], process.cwd());
|
|
28
90
|
if (result.exit_code === 0 && existsSync(outputPath)) {
|
|
29
|
-
return {
|
|
91
|
+
return {
|
|
92
|
+
captured: true,
|
|
93
|
+
paths: [outputPath],
|
|
94
|
+
method: appName ? `screencapture (full screen — could not find window "${appName}")` : "screencapture (full screen)",
|
|
95
|
+
};
|
|
30
96
|
}
|
|
31
97
|
return {
|
|
32
98
|
captured: false,
|
|
@@ -35,8 +101,53 @@ async function captureMacOS(outputPath) {
|
|
|
35
101
|
error: result.stderr || `screencapture exited with code ${result.exit_code}`,
|
|
36
102
|
};
|
|
37
103
|
}
|
|
38
|
-
async function captureWindows(outputPath) {
|
|
39
|
-
const
|
|
104
|
+
async function captureWindows(outputPath, appName) {
|
|
105
|
+
const hasPowershell = await checkToolAvailable("powershell");
|
|
106
|
+
if (!hasPowershell) {
|
|
107
|
+
return { captured: false, paths: [], method: "powershell", error: "powershell not found" };
|
|
108
|
+
}
|
|
109
|
+
let previousApp = "";
|
|
110
|
+
if (appName) {
|
|
111
|
+
previousApp = await bringAppToFront(appName);
|
|
112
|
+
}
|
|
113
|
+
let script;
|
|
114
|
+
if (appName) {
|
|
115
|
+
script = `
|
|
116
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
117
|
+
Add-Type -AssemblyName System.Drawing
|
|
118
|
+
Add-Type @"
|
|
119
|
+
using System;
|
|
120
|
+
using System.Runtime.InteropServices;
|
|
121
|
+
public class Win32 {
|
|
122
|
+
[DllImport("user32.dll")] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
|
|
123
|
+
[DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
|
|
124
|
+
[StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left, Top, Right, Bottom; }
|
|
125
|
+
}
|
|
126
|
+
"@
|
|
127
|
+
$procs = Get-Process | Where-Object { $_.MainWindowTitle -match '${appName}' -and $_.MainWindowHandle -ne 0 }
|
|
128
|
+
if ($procs.Count -gt 0) {
|
|
129
|
+
$hwnd = $procs[0].MainWindowHandle
|
|
130
|
+
$rect = New-Object Win32+RECT
|
|
131
|
+
[Win32]::GetWindowRect($hwnd, [ref]$rect)
|
|
132
|
+
$w = $rect.Right - $rect.Left
|
|
133
|
+
$h = $rect.Bottom - $rect.Top
|
|
134
|
+
$bitmap = New-Object System.Drawing.Bitmap($w, $h)
|
|
135
|
+
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
|
|
136
|
+
$graphics.CopyFromScreen($rect.Left, $rect.Top, 0, 0, (New-Object System.Drawing.Size($w, $h)))
|
|
137
|
+
$bitmap.Save('${outputPath.replace(/\\/g, "\\\\")}', [System.Drawing.Imaging.ImageFormat]::Png)
|
|
138
|
+
$graphics.Dispose(); $bitmap.Dispose()
|
|
139
|
+
} else {
|
|
140
|
+
$screen = [System.Windows.Forms.Screen]::PrimaryScreen
|
|
141
|
+
$bitmap = New-Object System.Drawing.Bitmap($screen.Bounds.Width, $screen.Bounds.Height)
|
|
142
|
+
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
|
|
143
|
+
$graphics.CopyFromScreen($screen.Bounds.Location, [System.Drawing.Point]::Empty, $screen.Bounds.Size)
|
|
144
|
+
$bitmap.Save('${outputPath.replace(/\\/g, "\\\\")}', [System.Drawing.Imaging.ImageFormat]::Png)
|
|
145
|
+
$graphics.Dispose(); $bitmap.Dispose()
|
|
146
|
+
}
|
|
147
|
+
`;
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
script = `
|
|
40
151
|
Add-Type -AssemblyName System.Windows.Forms
|
|
41
152
|
Add-Type -AssemblyName System.Drawing
|
|
42
153
|
$screen = [System.Windows.Forms.Screen]::PrimaryScreen
|
|
@@ -44,16 +155,15 @@ $bitmap = New-Object System.Drawing.Bitmap($screen.Bounds.Width, $screen.Bounds.
|
|
|
44
155
|
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
|
|
45
156
|
$graphics.CopyFromScreen($screen.Bounds.Location, [System.Drawing.Point]::Empty, $screen.Bounds.Size)
|
|
46
157
|
$bitmap.Save('${outputPath.replace(/\\/g, "\\\\")}', [System.Drawing.Imaging.ImageFormat]::Png)
|
|
47
|
-
$graphics.Dispose()
|
|
48
|
-
$bitmap.Dispose()
|
|
158
|
+
$graphics.Dispose(); $bitmap.Dispose()
|
|
49
159
|
`;
|
|
50
|
-
const hasPowershell = await checkToolAvailable("powershell");
|
|
51
|
-
if (!hasPowershell) {
|
|
52
|
-
return { captured: false, paths: [], method: "powershell", error: "powershell not found" };
|
|
53
160
|
}
|
|
54
161
|
const result = await runCommand("powershell", ["-NoProfile", "-Command", script], process.cwd());
|
|
162
|
+
if (previousApp && previousApp !== appName) {
|
|
163
|
+
await restorePreviousApp(previousApp);
|
|
164
|
+
}
|
|
55
165
|
if (result.exit_code === 0 && existsSync(outputPath)) {
|
|
56
|
-
return { captured: true, paths: [outputPath], method: "powershell" };
|
|
166
|
+
return { captured: true, paths: [outputPath], method: appName ? `powershell (window: ${appName})` : "powershell (full screen)" };
|
|
57
167
|
}
|
|
58
168
|
return {
|
|
59
169
|
captured: false,
|
|
@@ -62,25 +172,45 @@ $bitmap.Dispose()
|
|
|
62
172
|
error: result.stderr || `powershell exited with code ${result.exit_code}`,
|
|
63
173
|
};
|
|
64
174
|
}
|
|
65
|
-
async function captureLinux(outputPath) {
|
|
66
|
-
|
|
175
|
+
async function captureLinux(outputPath, appName) {
|
|
176
|
+
let previousApp = "";
|
|
177
|
+
if (appName) {
|
|
178
|
+
previousApp = await bringAppToFront(appName);
|
|
179
|
+
}
|
|
180
|
+
let captured = false;
|
|
181
|
+
if (appName && (await checkToolAvailable("xdotool")) && (await checkToolAvailable("import"))) {
|
|
182
|
+
const windowId = await findWindowId(appName);
|
|
183
|
+
if (windowId) {
|
|
184
|
+
const result = await runCommand("import", ["-window", windowId, outputPath], process.cwd());
|
|
185
|
+
if (result.exit_code === 0 && existsSync(outputPath)) {
|
|
186
|
+
captured = true;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (!captured && (await checkToolAvailable("import"))) {
|
|
67
191
|
const result = await runCommand("import", ["-window", "root", outputPath], process.cwd());
|
|
68
192
|
if (result.exit_code === 0 && existsSync(outputPath)) {
|
|
69
|
-
|
|
193
|
+
captured = true;
|
|
70
194
|
}
|
|
71
195
|
}
|
|
72
|
-
if (await checkToolAvailable("gnome-screenshot")) {
|
|
196
|
+
if (!captured && (await checkToolAvailable("gnome-screenshot"))) {
|
|
73
197
|
const result = await runCommand("gnome-screenshot", ["-f", outputPath], process.cwd());
|
|
74
198
|
if (result.exit_code === 0 && existsSync(outputPath)) {
|
|
75
|
-
|
|
199
|
+
captured = true;
|
|
76
200
|
}
|
|
77
201
|
}
|
|
78
|
-
if (await checkToolAvailable("scrot")) {
|
|
202
|
+
if (!captured && (await checkToolAvailable("scrot"))) {
|
|
79
203
|
const result = await runCommand("scrot", [outputPath], process.cwd());
|
|
80
204
|
if (result.exit_code === 0 && existsSync(outputPath)) {
|
|
81
|
-
|
|
205
|
+
captured = true;
|
|
82
206
|
}
|
|
83
207
|
}
|
|
208
|
+
if (previousApp && previousApp !== appName) {
|
|
209
|
+
await restorePreviousApp(previousApp);
|
|
210
|
+
}
|
|
211
|
+
if (captured) {
|
|
212
|
+
return { captured: true, paths: [outputPath], method: appName ? `screenshot (window: ${appName})` : "screenshot (full screen)" };
|
|
213
|
+
}
|
|
84
214
|
return {
|
|
85
215
|
captured: false,
|
|
86
216
|
paths: [],
|
|
@@ -88,9 +218,6 @@ async function captureLinux(outputPath) {
|
|
|
88
218
|
error: "No screenshot tool found (tried: import, gnome-screenshot, scrot)",
|
|
89
219
|
};
|
|
90
220
|
}
|
|
91
|
-
/**
|
|
92
|
-
* List all PNG screenshots already present in a directory.
|
|
93
|
-
*/
|
|
94
221
|
export function listScreenshots(dir) {
|
|
95
222
|
if (!existsSync(dir))
|
|
96
223
|
return [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../src/runners/screenshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../src/runners/screenshot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { TargetType } from "./window_manager.js";
|
|
2
|
+
export interface VideoRecordResult {
|
|
3
|
+
recorded: boolean;
|
|
4
|
+
path: string;
|
|
5
|
+
duration_seconds: number;
|
|
6
|
+
method: string;
|
|
7
|
+
error?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface BackgroundRecordingHandle {
|
|
10
|
+
recording_id: string;
|
|
11
|
+
output_path: string;
|
|
12
|
+
app_name: string;
|
|
13
|
+
previous_app: string;
|
|
14
|
+
started_at: number;
|
|
15
|
+
target_type: TargetType;
|
|
16
|
+
log_capture: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Blocking video recording. Brings app to front, records for a fixed
|
|
20
|
+
* duration, then restores the previous frontmost app.
|
|
21
|
+
*/
|
|
22
|
+
export declare function recordVideo(outputDir: string, durationSeconds?: number, appName?: string): Promise<VideoRecordResult & {
|
|
23
|
+
log_path?: string;
|
|
24
|
+
}>;
|
|
25
|
+
/**
|
|
26
|
+
* Start recording in the background. Returns a handle immediately so the
|
|
27
|
+
* agent can interact with the app while recording is active.
|
|
28
|
+
* Call stopBackgroundRecording() when done.
|
|
29
|
+
*
|
|
30
|
+
* targetType selects the capture method:
|
|
31
|
+
* - "desktop": ffmpeg screen capture (macOS/Windows/Linux)
|
|
32
|
+
* - "android_emulator": adb shell screenrecord
|
|
33
|
+
* - "ios_simulator": xcrun simctl io booted recordVideo
|
|
34
|
+
* - "browser": ffmpeg or Playwright recordVideo
|
|
35
|
+
*/
|
|
36
|
+
export declare function startBackgroundRecording(outputDir: string, appName: string, maxDurationSeconds?: number, targetType?: TargetType): Promise<BackgroundRecordingHandle | {
|
|
37
|
+
error: string;
|
|
38
|
+
}>;
|
|
39
|
+
/**
|
|
40
|
+
* Stop a background recording. Sends SIGINT to finalize the video file,
|
|
41
|
+
* then restores the previous frontmost app.
|
|
42
|
+
* For Android, pulls the recorded file from the device.
|
|
43
|
+
*/
|
|
44
|
+
export declare function stopBackgroundRecording(recordingId: string): Promise<VideoRecordResult & {
|
|
45
|
+
log_path?: string;
|
|
46
|
+
}>;
|
|
47
|
+
/** List all active background recordings. */
|
|
48
|
+
export declare function listActiveRecordings(): string[];
|
|
49
|
+
//# sourceMappingURL=video_recorder.d.ts.map
|
|
@@ -0,0 +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,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"}
|