@cool-mcp/desktop-automation 1.0.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.
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Desktop Automation MCP Types
3
+ */
4
+ export interface WindowInfo {
5
+ title: string;
6
+ owner: {
7
+ name: string;
8
+ processId: number;
9
+ bundleId?: string;
10
+ path?: string;
11
+ };
12
+ bounds: {
13
+ x: number;
14
+ y: number;
15
+ width: number;
16
+ height: number;
17
+ };
18
+ }
19
+ export interface DisplayInfo {
20
+ id: number;
21
+ name: string;
22
+ x: number;
23
+ y: number;
24
+ width: number;
25
+ height: number;
26
+ scaleFactor: number;
27
+ isPrimary: boolean;
28
+ }
29
+ export interface ScreenshotOutput {
30
+ base64: string;
31
+ width: number;
32
+ height: number;
33
+ scaleFactor: number;
34
+ windowBounds?: {
35
+ x: number;
36
+ y: number;
37
+ width: number;
38
+ height: number;
39
+ };
40
+ }
41
+ export interface BBox {
42
+ x1: number;
43
+ y1: number;
44
+ x2: number;
45
+ y2: number;
46
+ }
47
+ export interface ScreenCoords {
48
+ x: number;
49
+ y: number;
50
+ }
51
+ export interface CoordConvertParams {
52
+ bbox: BBox;
53
+ windowBounds: {
54
+ x: number;
55
+ y: number;
56
+ width: number;
57
+ height: number;
58
+ };
59
+ scaleFactor?: number;
60
+ }
61
+ export type MouseButton = 'left' | 'right' | 'middle';
62
+ export type ScrollDirection = 'up' | 'down' | 'left' | 'right';
63
+ export interface OperationResult {
64
+ success: boolean;
65
+ message?: string;
66
+ data?: unknown;
67
+ }
68
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,MAAM,EAAE;QACN,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;QACV,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAGD,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;CACpB;AAGD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE;QACb,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;QACV,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAGD,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ;AAGD,MAAM,WAAW,YAAY;IAC3B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAGD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,IAAI,CAAC;IACX,YAAY,EAAE;QACZ,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;QACV,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAGD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AACtD,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAG/D,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Desktop Automation MCP Types
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Utility functions for coordinate conversion and helpers
3
+ */
4
+ import type { BBox, ScreenCoords, CoordConvertParams } from './types.js';
5
+ export declare const DEFAULT_FACTOR = 1000;
6
+ /**
7
+ * 将 bbox (0-1000 归一化坐标) 转换为屏幕像素坐标
8
+ *
9
+ * 流程:
10
+ * 1. bbox 是模型输出的 0-1000 归一化坐标
11
+ * 2. 先转换为 0-1 归一化坐标
12
+ * 3. 再根据窗口尺寸转换为窗口内的像素坐标
13
+ * 4. 最后加上窗口在屏幕中的偏移量,得到屏幕绝对坐标
14
+ */
15
+ export declare function bboxToScreenCoords(params: CoordConvertParams): ScreenCoords;
16
+ /**
17
+ * 解析 bbox 字符串
18
+ * 支持格式: "x1 y1 x2 y2" 或 "[x1, y1, x2, y2]" 或 "<bbox>x1 y1 x2 y2</bbox>"
19
+ */
20
+ export declare function parseBBox(bboxStr: string): BBox | null;
21
+ /**
22
+ * 延迟函数
23
+ */
24
+ export declare function sleep(ms: number): Promise<void>;
25
+ /**
26
+ * 获取平台信息
27
+ */
28
+ export declare function getPlatform(): 'darwin' | 'win32' | 'linux';
29
+ /**
30
+ * 检查是否为 macOS
31
+ */
32
+ export declare function isMacOS(): boolean;
33
+ /**
34
+ * 检查是否为 Windows
35
+ */
36
+ export declare function isWindows(): boolean;
37
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGzE,eAAO,MAAM,cAAc,OAAO,CAAC;AAEnC;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,YAAY,CAsB3E;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAoBtD;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,QAAQ,GAAG,OAAO,GAAG,OAAO,CAE1D;AAED;;GAEG;AACH,wBAAgB,OAAO,IAAI,OAAO,CAEjC;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAEnC"}
package/dist/utils.js ADDED
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Utility functions for coordinate conversion and helpers
3
+ */
4
+ // 默认归一化因子 (模型输出 0-1000 范围)
5
+ export const DEFAULT_FACTOR = 1000;
6
+ /**
7
+ * 将 bbox (0-1000 归一化坐标) 转换为屏幕像素坐标
8
+ *
9
+ * 流程:
10
+ * 1. bbox 是模型输出的 0-1000 归一化坐标
11
+ * 2. 先转换为 0-1 归一化坐标
12
+ * 3. 再根据窗口尺寸转换为窗口内的像素坐标
13
+ * 4. 最后加上窗口在屏幕中的偏移量,得到屏幕绝对坐标
14
+ */
15
+ export function bboxToScreenCoords(params) {
16
+ const { bbox, windowBounds, scaleFactor = 1 } = params;
17
+ const { x1, y1, x2, y2 } = bbox;
18
+ const { x: winX, y: winY, width: winWidth, height: winHeight } = windowBounds;
19
+ // 计算 bbox 中心点 (0-1000 范围)
20
+ const centerX = (x1 + x2) / 2;
21
+ const centerY = (y1 + y2) / 2;
22
+ // 转换为 0-1 归一化坐标
23
+ const normalizedX = centerX / DEFAULT_FACTOR;
24
+ const normalizedY = centerY / DEFAULT_FACTOR;
25
+ // 转换为窗口内的像素坐标
26
+ const windowPixelX = normalizedX * winWidth;
27
+ const windowPixelY = normalizedY * winHeight;
28
+ // 加上窗口偏移量,得到屏幕绝对坐标
29
+ const screenX = Math.round(winX + windowPixelX);
30
+ const screenY = Math.round(winY + windowPixelY);
31
+ return { x: screenX, y: screenY };
32
+ }
33
+ /**
34
+ * 解析 bbox 字符串
35
+ * 支持格式: "x1 y1 x2 y2" 或 "[x1, y1, x2, y2]" 或 "<bbox>x1 y1 x2 y2</bbox>"
36
+ */
37
+ export function parseBBox(bboxStr) {
38
+ // 移除 <bbox> 标签
39
+ let cleaned = bboxStr.replace(/<\/?bbox>/g, '').trim();
40
+ // 移除方括号
41
+ cleaned = cleaned.replace(/[\[\]]/g, '');
42
+ // 分割数字
43
+ const numbers = cleaned.split(/[\s,]+/).map(n => parseFloat(n.trim())).filter(n => !isNaN(n));
44
+ if (numbers.length < 4) {
45
+ return null;
46
+ }
47
+ return {
48
+ x1: numbers[0],
49
+ y1: numbers[1],
50
+ x2: numbers[2],
51
+ y2: numbers[3]
52
+ };
53
+ }
54
+ /**
55
+ * 延迟函数
56
+ */
57
+ export function sleep(ms) {
58
+ return new Promise(resolve => setTimeout(resolve, ms));
59
+ }
60
+ /**
61
+ * 获取平台信息
62
+ */
63
+ export function getPlatform() {
64
+ return process.platform;
65
+ }
66
+ /**
67
+ * 检查是否为 macOS
68
+ */
69
+ export function isMacOS() {
70
+ return process.platform === 'darwin';
71
+ }
72
+ /**
73
+ * 检查是否为 Windows
74
+ */
75
+ export function isWindows() {
76
+ return process.platform === 'win32';
77
+ }
78
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,2BAA2B;AAC3B,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC;AAEnC;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAA0B;IAC3D,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC;IACvD,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,YAAY,CAAC;IAE9E,0BAA0B;IAC1B,MAAM,OAAO,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,OAAO,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IAE9B,gBAAgB;IAChB,MAAM,WAAW,GAAG,OAAO,GAAG,cAAc,CAAC;IAC7C,MAAM,WAAW,GAAG,OAAO,GAAG,cAAc,CAAC;IAE7C,cAAc;IACd,MAAM,YAAY,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC5C,MAAM,YAAY,GAAG,WAAW,GAAG,SAAS,CAAC;IAE7C,mBAAmB;IACnB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,YAAY,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,YAAY,CAAC,CAAC;IAEhD,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;AACpC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,eAAe;IACf,IAAI,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAEvD,QAAQ;IACR,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAEzC,OAAO;IACP,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9F,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;QACd,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;QACd,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;QACd,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;KACf,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,KAAK,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW;IACzB,OAAO,OAAO,CAAC,QAAwC,CAAC;AAC1D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,OAAO;IACrB,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;AACtC,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Window Manager - 窗口管理模块
3
+ * 支持 macOS 和 Windows
4
+ */
5
+ import type { WindowInfo } from './types.js';
6
+ /**
7
+ * 根据进程名激活窗口(置顶)
8
+ * @param processName 进程名称
9
+ * @param title 窗口标题(可选,用于更精确匹配)
10
+ */
11
+ export declare function activateWindow(processName: string, title?: string): Promise<boolean>;
12
+ /**
13
+ * 获取当前活动窗口信息
14
+ */
15
+ export declare function getActiveWindow(): Promise<WindowInfo | null>;
16
+ /**
17
+ * 根据进程名获取窗口信息
18
+ */
19
+ export declare function getWindowByProcess(processName: string): Promise<WindowInfo | null>;
20
+ /**
21
+ * 列出所有窗口
22
+ */
23
+ export declare function listWindows(): Promise<WindowInfo[]>;
24
+ //# sourceMappingURL=window-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"window-manager.d.ts","sourceRoot":"","sources":["../src/window-manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAO7C;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAyD1F;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAyGlE;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CA4FxF;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAsFzD"}
@@ -0,0 +1,368 @@
1
+ /**
2
+ * Window Manager - 窗口管理模块
3
+ * 支持 macOS 和 Windows
4
+ */
5
+ import { exec } from 'child_process';
6
+ import { promisify } from 'util';
7
+ import { isMacOS, isWindows } from './utils.js';
8
+ const execAsync = promisify(exec);
9
+ /**
10
+ * 根据进程名激活窗口(置顶)
11
+ * @param processName 进程名称
12
+ * @param title 窗口标题(可选,用于更精确匹配)
13
+ */
14
+ export async function activateWindow(processName, title) {
15
+ try {
16
+ if (isMacOS()) {
17
+ // 直接使用传入的进程名激活(agent 应从 listWindows 获取准确的进程名)
18
+ try {
19
+ const script = `
20
+ tell application "System Events"
21
+ tell process "${processName}"
22
+ set frontmost to true
23
+ if (count of windows) > 0 then
24
+ perform action "AXRaise" of window 1
25
+ end if
26
+ end tell
27
+ end tell
28
+ `;
29
+ await execAsync(`osascript -e '${script}'`);
30
+ return true;
31
+ }
32
+ catch (e) {
33
+ // 失败
34
+ }
35
+ return false;
36
+ }
37
+ else if (isWindows()) {
38
+ // Windows: 使用 PowerShell
39
+ const script = `
40
+ Add-Type @"
41
+ using System;
42
+ using System.Runtime.InteropServices;
43
+ public class Win32 {
44
+ [DllImport("user32.dll")]
45
+ public static extern bool SetForegroundWindow(IntPtr hWnd);
46
+ [DllImport("user32.dll")]
47
+ public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
48
+ [DllImport("user32.dll")]
49
+ public static extern bool IsIconic(IntPtr hWnd);
50
+ }
51
+ "@
52
+ $process = Get-Process | Where-Object { $_.ProcessName -like "*${processName}*" -and $_.MainWindowHandle -ne 0 } | Select-Object -First 1
53
+ if ($process) {
54
+ # 如果窗口最小化,先恢复
55
+ if ([Win32]::IsIconic($process.MainWindowHandle)) {
56
+ [Win32]::ShowWindow($process.MainWindowHandle, 9)
57
+ }
58
+ [Win32]::SetForegroundWindow($process.MainWindowHandle)
59
+ Write-Output "OK"
60
+ } else {
61
+ Write-Output "NOT_FOUND"
62
+ }
63
+ `;
64
+ const { stdout } = await execAsync(`powershell -Command "${script.replace(/"/g, '\\"').replace(/\n/g, ' ')}"`, { shell: 'powershell.exe' });
65
+ return stdout.trim() === 'OK';
66
+ }
67
+ return false;
68
+ }
69
+ catch (error) {
70
+ console.error('Failed to activate window:', error);
71
+ return false;
72
+ }
73
+ }
74
+ /**
75
+ * 获取当前活动窗口信息
76
+ */
77
+ export async function getActiveWindow() {
78
+ const SEP = ':::SEP:::';
79
+ try {
80
+ if (isMacOS()) {
81
+ // 使用 focused window 而不是 first window,确保获取真正激活的窗口
82
+ const script = `
83
+ tell application "System Events"
84
+ set frontApp to first application process whose frontmost is true
85
+ set appName to name of frontApp
86
+ set appId to unix id of frontApp
87
+ tell frontApp
88
+ set winCount to count of windows
89
+ if winCount > 0 then
90
+ -- 尝试获取 focused window,如果失败则用 first window
91
+ try
92
+ set frontWin to (first window whose value of attribute "AXMain" is true)
93
+ on error
94
+ set frontWin to first window
95
+ end try
96
+ set winTitle to name of frontWin
97
+ set winPos to position of frontWin
98
+ set winSize to size of frontWin
99
+ -- 调试:输出窗口数量
100
+ return appName & ":::SEP:::" & appId & ":::SEP:::" & winTitle & ":::SEP:::" & (item 1 of winPos) & "," & (item 2 of winPos) & "," & (item 1 of winSize) & "," & (item 2 of winSize) & ":::SEP:::" & winCount
101
+ else
102
+ return appName & ":::SEP:::" & appId & ":::SEP:::" & ":::SEP:::" & "0,0,800,600" & ":::SEP:::" & "0"
103
+ end if
104
+ end tell
105
+ end tell
106
+ `;
107
+ const { stdout, stderr } = await execAsync(`osascript -e '${script}'`);
108
+ console.error(`[getActiveWindow] AppleScript stdout: ${stdout.trim()}`);
109
+ if (stderr)
110
+ console.error(`[getActiveWindow] AppleScript stderr: ${stderr}`);
111
+ const parts = stdout.trim().split(SEP);
112
+ if (parts.length >= 4) {
113
+ const bounds = parts[3].split(',').map(n => parseInt(n.trim()));
114
+ const winCount = parts[4] ? parseInt(parts[4]) : 0;
115
+ console.error(`[getActiveWindow] 解析结果: app=${parts[0]}, title=${parts[2]}, bounds=${parts[3]}, winCount=${winCount}`);
116
+ return {
117
+ title: parts[2],
118
+ owner: {
119
+ name: parts[0],
120
+ processId: parseInt(parts[1])
121
+ },
122
+ bounds: {
123
+ x: bounds[0] || 0,
124
+ y: bounds[1] || 0,
125
+ width: bounds[2] || 800,
126
+ height: bounds[3] || 600
127
+ }
128
+ };
129
+ }
130
+ }
131
+ else if (isWindows()) {
132
+ const script = `
133
+ Add-Type @"
134
+ using System;
135
+ using System.Runtime.InteropServices;
136
+ using System.Text;
137
+ public class Win32Active {
138
+ [DllImport("user32.dll")]
139
+ public static extern IntPtr GetForegroundWindow();
140
+ [DllImport("user32.dll")]
141
+ public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
142
+ [DllImport("user32.dll")]
143
+ public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
144
+ [DllImport("user32.dll")]
145
+ public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
146
+ [StructLayout(LayoutKind.Sequential)]
147
+ public struct RECT { public int Left, Top, Right, Bottom; }
148
+ }
149
+ "@
150
+ $hwnd = [Win32Active]::GetForegroundWindow()
151
+ $title = New-Object System.Text.StringBuilder 256
152
+ [Win32Active]::GetWindowText($hwnd, $title, 256)
153
+ $processId = 0
154
+ [Win32Active]::GetWindowThreadProcessId($hwnd, [ref]$processId)
155
+ $process = Get-Process -Id $processId
156
+ $rect = New-Object Win32Active+RECT
157
+ [Win32Active]::GetWindowRect($hwnd, [ref]$rect)
158
+ Write-Output "$($process.ProcessName)|$processId|$($title.ToString())|$($rect.Left),$($rect.Top),$($rect.Right - $rect.Left),$($rect.Bottom - $rect.Top)"
159
+ `;
160
+ const { stdout } = await execAsync(`powershell -Command "${script.replace(/"/g, '\\"').replace(/\n/g, ' ')}"`, { shell: 'powershell.exe' });
161
+ const parts = stdout.trim().split('|');
162
+ if (parts.length >= 4) {
163
+ const bounds = parts[3].split(',').map(n => parseInt(n.trim()));
164
+ return {
165
+ title: parts[2],
166
+ owner: {
167
+ name: parts[0],
168
+ processId: parseInt(parts[1])
169
+ },
170
+ bounds: {
171
+ x: bounds[0] || 0,
172
+ y: bounds[1] || 0,
173
+ width: bounds[2] || 800,
174
+ height: bounds[3] || 600
175
+ }
176
+ };
177
+ }
178
+ }
179
+ return null;
180
+ }
181
+ catch (error) {
182
+ console.error('Failed to get active window:', error);
183
+ return null;
184
+ }
185
+ }
186
+ /**
187
+ * 根据进程名获取窗口信息
188
+ */
189
+ export async function getWindowByProcess(processName) {
190
+ const SEP = ':::SEP:::';
191
+ try {
192
+ if (isMacOS()) {
193
+ // 直接使用传入的进程名查找
194
+ const script = `
195
+ tell application "System Events"
196
+ tell process "${processName}"
197
+ set procId to unix id
198
+ set winBounds to {0, 0, 800, 600}
199
+ set winTitle to ""
200
+ if (count of windows) > 0 then
201
+ set frontWin to first window
202
+ set winTitle to name of frontWin
203
+ set winPos to position of frontWin
204
+ set winSize to size of frontWin
205
+ set winBounds to {item 1 of winPos, item 2 of winPos, item 1 of winSize, item 2 of winSize}
206
+ end if
207
+ return "${processName}" & ":::SEP:::" & procId & ":::SEP:::" & winTitle & ":::SEP:::" & (item 1 of winBounds) & "," & (item 2 of winBounds) & "," & (item 3 of winBounds) & "," & (item 4 of winBounds)
208
+ end tell
209
+ end tell
210
+ `;
211
+ const { stdout } = await execAsync(`osascript -e '${script}'`);
212
+ const parts = stdout.trim().split(SEP);
213
+ if (parts.length >= 4) {
214
+ const bounds = parts[3].split(',').map(n => parseInt(n.trim()));
215
+ return {
216
+ title: parts[2],
217
+ owner: {
218
+ name: parts[0],
219
+ processId: parseInt(parts[1])
220
+ },
221
+ bounds: {
222
+ x: bounds[0] || 0,
223
+ y: bounds[1] || 0,
224
+ width: bounds[2] || 800,
225
+ height: bounds[3] || 600
226
+ }
227
+ };
228
+ }
229
+ return null;
230
+ }
231
+ else if (isWindows()) {
232
+ const script = `
233
+ Add-Type @"
234
+ using System;
235
+ using System.Runtime.InteropServices;
236
+ public class Win32Rect {
237
+ [DllImport("user32.dll")]
238
+ public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
239
+ [StructLayout(LayoutKind.Sequential)]
240
+ public struct RECT { public int Left, Top, Right, Bottom; }
241
+ }
242
+ "@
243
+ $process = Get-Process | Where-Object { $_.ProcessName -like "*${processName}*" -and $_.MainWindowHandle -ne 0 } | Select-Object -First 1
244
+ if ($process) {
245
+ $rect = New-Object Win32Rect+RECT
246
+ [Win32Rect]::GetWindowRect($process.MainWindowHandle, [ref]$rect)
247
+ Write-Output "$($process.ProcessName)|$($process.Id)|$($process.MainWindowTitle)|$($rect.Left),$($rect.Top),$($rect.Right - $rect.Left),$($rect.Bottom - $rect.Top)"
248
+ } else {
249
+ Write-Output "NOT_FOUND"
250
+ }
251
+ `;
252
+ const { stdout } = await execAsync(`powershell -Command "${script.replace(/"/g, '\\"').replace(/\n/g, ' ')}"`, { shell: 'powershell.exe' });
253
+ if (stdout.trim() === 'NOT_FOUND') {
254
+ return null;
255
+ }
256
+ const parts = stdout.trim().split('|');
257
+ if (parts.length >= 4) {
258
+ const bounds = parts[3].split(',').map(n => parseInt(n.trim()));
259
+ return {
260
+ title: parts[2],
261
+ owner: {
262
+ name: parts[0],
263
+ processId: parseInt(parts[1])
264
+ },
265
+ bounds: {
266
+ x: bounds[0] || 0,
267
+ y: bounds[1] || 0,
268
+ width: bounds[2] || 800,
269
+ height: bounds[3] || 600
270
+ }
271
+ };
272
+ }
273
+ }
274
+ return null;
275
+ }
276
+ catch (error) {
277
+ console.error('Failed to get window by process:', error);
278
+ return null;
279
+ }
280
+ }
281
+ /**
282
+ * 列出所有窗口
283
+ */
284
+ export async function listWindows() {
285
+ const SEP = ':::SEP:::';
286
+ try {
287
+ if (isMacOS()) {
288
+ // 获取所有前台进程
289
+ const { stdout: procList } = await execAsync(`osascript -e 'tell application "System Events" to get name of every process whose background only is false'`);
290
+ const procNames = procList.trim().split(', ');
291
+ const windows = [];
292
+ // 逐个获取窗口信息
293
+ for (const procName of procNames) {
294
+ try {
295
+ const script = `
296
+ tell application "System Events"
297
+ tell process "${procName}"
298
+ set procId to unix id
299
+ if (count of windows) > 0 then
300
+ set frontWin to first window
301
+ set winTitle to name of frontWin
302
+ set winPos to position of frontWin
303
+ set winSize to size of frontWin
304
+ return winTitle & ":::SEP:::" & (item 1 of winPos) & "," & (item 2 of winPos) & "," & (item 1 of winSize) & "," & (item 2 of winSize) & ":::SEP:::" & procId
305
+ end if
306
+ end tell
307
+ end tell
308
+ `;
309
+ const { stdout } = await execAsync(`osascript -e '${script.replace(/'/g, "'\"'\"'")}'`);
310
+ const result = stdout.trim();
311
+ if (result) {
312
+ const parts = result.split(SEP);
313
+ if (parts.length >= 3) {
314
+ const bounds = parts[1].split(',').map(n => parseInt(n.trim()));
315
+ windows.push({
316
+ title: parts[0],
317
+ owner: {
318
+ name: procName,
319
+ processId: parseInt(parts[2]) || 0
320
+ },
321
+ bounds: {
322
+ x: bounds[0] || 0,
323
+ y: bounds[1] || 0,
324
+ width: bounds[2] || 800,
325
+ height: bounds[3] || 600
326
+ }
327
+ });
328
+ }
329
+ }
330
+ }
331
+ catch (e) {
332
+ // 忽略单个进程的错误
333
+ }
334
+ }
335
+ return windows;
336
+ }
337
+ else if (isWindows()) {
338
+ const script = `
339
+ Get-Process | Where-Object { $_.MainWindowHandle -ne 0 } | ForEach-Object {
340
+ Write-Output "$($_.ProcessName)|$($_.Id)|$($_.MainWindowTitle)"
341
+ }
342
+ `;
343
+ const { stdout } = await execAsync(`powershell -Command "${script.replace(/\n/g, ' ')}"`, { shell: 'powershell.exe' });
344
+ const windows = [];
345
+ const lines = stdout.trim().split('\n');
346
+ for (const line of lines) {
347
+ const parts = line.trim().split('|');
348
+ if (parts.length >= 3) {
349
+ windows.push({
350
+ title: parts[2],
351
+ owner: {
352
+ name: parts[0],
353
+ processId: parseInt(parts[1])
354
+ },
355
+ bounds: { x: 0, y: 0, width: 800, height: 600 }
356
+ });
357
+ }
358
+ }
359
+ return windows;
360
+ }
361
+ return [];
362
+ }
363
+ catch (error) {
364
+ console.error('Failed to list windows:', error);
365
+ return [];
366
+ }
367
+ }
368
+ //# sourceMappingURL=window-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"window-manager.js","sourceRoot":"","sources":["../src/window-manager.ts"],"names":[],"mappings":"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"}