ucu-mcp 0.6.6 → 0.6.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/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,40 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.6.7] - 2026-06-18
|
|
9
|
+
|
|
10
|
+
Claude Code 实机测试暴露的致命 bug:Chromium/Electron app 操控完全失败。
|
|
11
|
+
|
|
12
|
+
### P0 Fixed — Chromium/Electron app 操控失败根因
|
|
13
|
+
|
|
14
|
+
- **windowlist-helper 只返回当前屏幕可见窗口**(windowlist/main.swift):`.optionOnScreenOnly` 导致其他 Space / 最小化 / 被遮挡的窗口不可见。Microsoft Edge(14 个窗口)完全不在列表里 → `focus_app("Microsoft Edge")` 找不到窗口 → 退到 tray fallback → 返回 `windowId:"tray"` → 所有后续操作发到错误 pid。**修复**:改为 `[.optionAll, .excludeDesktopElements]`(80 个窗口全可见),TS 层用 `isOnScreen` 过滤。
|
|
15
|
+
- **selectWindowForApp 多窗口选择缺陷**(helpers.ts):Chromium app 暴露多个 compositor 子窗口,`find` 第一个可能不是主浏览器窗口。**修复**:改为评分排序(isOnScreen +1000, has title +500, 最大面积),优先选可见有标题的大窗口。
|
|
16
|
+
|
|
17
|
+
### P0 Fixed — 浏览器操作必要快捷键被屏蔽
|
|
18
|
+
|
|
19
|
+
- **cmd+l 从 blocklist 移除**(guard.ts):cmd+l = 浏览器聚焦地址栏(必要操作),不是锁屏(现代 macOS 用 ctrl+cmd+q)。屏蔽它让浏览器自动化完全不可能。
|
|
20
|
+
- **cmd+w 从 blocklist 移除**(guard.ts):cmd+w = 关闭标签页(常用操作)。
|
|
21
|
+
- 新增 `ctrl+cmd+q`(现代 macOS 锁屏)到 blocklist。
|
|
22
|
+
|
|
23
|
+
### 根因分析
|
|
24
|
+
|
|
25
|
+
Claude Code 报告的 5 个连锁失败全部源于同一根因——windowlist 看不到 Edge 窗口:
|
|
26
|
+
1. focus_app 返回 tray → pid 错误(tray helper 而非浏览器进程)
|
|
27
|
+
2. press_key 到错误 pid → 假装成功
|
|
28
|
+
3. type_text 无 target → 强制 HID → 打到前台终端
|
|
29
|
+
4. find_element 返回空 → AX 树不可见(Chromium 正常,但 windowlist 问题是额外障碍)
|
|
30
|
+
5. 截图只显示前台 app → 无法验证操作效果
|
|
31
|
+
|
|
32
|
+
修复 1(windowlist .optionAll)解决了 1/2/3/5;修复 2(cmd+l/w)解决了 4 的连锁影响。
|
|
33
|
+
|
|
34
|
+
### Tests
|
|
35
|
+
|
|
36
|
+
- 330 passed(+2:cmd+l/cmd+w allow + ctrl+cmd+q block)。
|
|
37
|
+
|
|
38
|
+
## [0.6.6] - 2026-06-18
|
|
39
|
+
|
|
40
|
+
Skill 重写修复抢前台 + 菜单栏误用。
|
|
41
|
+
|
|
8
42
|
## [0.6.5] - 2026-06-18
|
|
9
43
|
|
|
10
44
|
Code review P2 加固(3 批次):安全面 + 输入正确性 + 日志卫生。
|
|
@@ -58,6 +58,18 @@ export function appNameMatches(processName, requestedApp) {
|
|
|
58
58
|
}
|
|
59
59
|
export function selectWindowForApp(windows, requestedApp) {
|
|
60
60
|
const requested = normalizeAppName(requestedApp);
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
const matched = windows.filter((window) => normalizeAppName(window.processName) === requested);
|
|
62
|
+
const pool = matched.length > 0 ? matched : windows.filter((window) => appNameMatches(window.processName, requestedApp));
|
|
63
|
+
if (pool.length === 0)
|
|
64
|
+
return undefined;
|
|
65
|
+
if (pool.length === 1)
|
|
66
|
+
return pool[0];
|
|
67
|
+
// Multiple windows for the same app (common for Chromium/Electron which expose
|
|
68
|
+
// many compositor sub-windows). Prefer: onScreen → has title → largest area.
|
|
69
|
+
const scored = pool.map((w) => ({
|
|
70
|
+
w,
|
|
71
|
+
score: (w.isOnScreen ? 1000 : 0) + (w.title ? 500 : 0) + (w.bounds.width * w.bounds.height),
|
|
72
|
+
}));
|
|
73
|
+
scored.sort((a, b) => b.score - a.score);
|
|
74
|
+
return scored[0].w;
|
|
63
75
|
}
|
package/dist/src/safety/guard.js
CHANGED
|
@@ -10,15 +10,18 @@
|
|
|
10
10
|
// Built-in blocked shortcuts
|
|
11
11
|
// ---------------------------------------------------------------------------
|
|
12
12
|
const DEFAULT_BLOCKED_KEYS = [
|
|
13
|
-
// macOS – app
|
|
14
|
-
"cmd+q",
|
|
13
|
+
// macOS – truly irreversible app/system actions
|
|
14
|
+
"cmd+q", // quit app (data loss risk)
|
|
15
15
|
"cmd+shift+q", // log out(方向2 后字母 q 可解析,须显式拦截)
|
|
16
16
|
"cmd+option+q", // log out variant
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
// NOTE: cmd+l (lock screen / browser address bar) and cmd+w (close tab) were
|
|
18
|
+
// previously blocked, but they are essential for browser automation (cmd+l =
|
|
19
|
+
// focus address bar, cmd+w = close tab). Lock screen on modern macOS is
|
|
20
|
+
// ctrl+cmd+q, not cmd+l. Removed from blocklist v0.6.7.
|
|
19
21
|
// macOS – system-level
|
|
20
22
|
"cmd+option+esc", // Force-quit dialog
|
|
21
23
|
"cmd+ctrl+power", // force restart
|
|
24
|
+
"ctrl+cmd+q", // lock screen (modern macOS)
|
|
22
25
|
"cmd+option+power", // sleep
|
|
23
26
|
// Windows / Linux
|
|
24
27
|
"alt+f4",
|
|
@@ -28,7 +28,10 @@ struct Output: Encodable {
|
|
|
28
28
|
let error: String?
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
// .optionAll includes windows on all Spaces + minimized windows. We filter by
|
|
32
|
+
// isOnScreen in the TS layer. Using .optionOnScreenOnly would miss windows on
|
|
33
|
+
// other Spaces or minimized ones, causing focus_app to fail for any background app.
|
|
34
|
+
let options: CGWindowListOption = [.optionAll, .excludeDesktopElements]
|
|
32
35
|
guard let windowList = CGWindowListCopyWindowInfo(options, kCGNullWindowID) as? [[String: Any]] else {
|
|
33
36
|
let out = Output(windows: [], error: "CGWindowListCopyWindowInfo returned nil")
|
|
34
37
|
FileHandle.standardOutput.write(try! JSONEncoder().encode(out))
|
|
Binary file
|