@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.
- package/README.md +225 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +671 -0
- package/dist/index.js.map +1 -0
- package/dist/input-controller.d.ts +63 -0
- package/dist/input-controller.d.ts.map +1 -0
- package/dist/input-controller.js +232 -0
- package/dist/input-controller.js.map +1 -0
- package/dist/screenshot.d.ts +22 -0
- package/dist/screenshot.d.ts.map +1 -0
- package/dist/screenshot.js +247 -0
- package/dist/screenshot.js.map +1 -0
- package/dist/types.d.ts +68 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +37 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +78 -0
- package/dist/utils.js.map +1 -0
- package/dist/window-manager.d.ts +24 -0
- package/dist/window-manager.d.ts.map +1 -0
- package/dist/window-manager.js +368 -0
- package/dist/window-manager.js.map +1 -0
- package/package.json +55 -0
package/dist/types.d.ts
ADDED
|
@@ -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 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
package/dist/utils.d.ts
ADDED
|
@@ -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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"}
|