cicy-desktop 2.1.208 → 2.1.209
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cicy-desktop",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.209",
|
|
4
4
|
"description": "CiCy - AI-powered operating system browser",
|
|
5
5
|
"main": "src/main.js",
|
|
6
6
|
"bin": {
|
|
@@ -140,11 +140,11 @@
|
|
|
140
140
|
"//optionalDependencies": "(2026-06 回调): mac/linux 改回 native cicy-code(:8008,colima 在 16G mac 上压垮内存)→ 重新内置 cicy-code-<plat> / cicy-mihomo-<plat>,localbin.fromBundle 零网络 seed(npm 仅作更新通道,带 npmmirror→npmjs 回退)。这些由 scripts/sync-runtime-deps.cjs 在 tag-push 时同步到最新版。npm 的 os/cpu 字段保证每个平台只装自己那份。Windows 仍走 docker(WSL :8009),它那份 cicy-code-windows 用不到但 bundle 着无害。",
|
|
141
141
|
"optionalDependencies": {
|
|
142
142
|
"electron": "41.0.3",
|
|
143
|
-
"cicy-code-darwin-x64": "2.3.
|
|
144
|
-
"cicy-code-darwin-arm64": "2.3.
|
|
145
|
-
"cicy-code-linux-x64": "2.3.
|
|
146
|
-
"cicy-code-linux-arm64": "2.3.
|
|
147
|
-
"cicy-code-windows-x64": "2.3.
|
|
143
|
+
"cicy-code-darwin-x64": "2.3.54",
|
|
144
|
+
"cicy-code-darwin-arm64": "2.3.54",
|
|
145
|
+
"cicy-code-linux-x64": "2.3.54",
|
|
146
|
+
"cicy-code-linux-arm64": "2.3.54",
|
|
147
|
+
"cicy-code-windows-x64": "2.3.54",
|
|
148
148
|
"cicy-mihomo-darwin-x64": "1.10.4",
|
|
149
149
|
"cicy-mihomo-darwin-arm64": "1.10.4",
|
|
150
150
|
"cicy-mihomo-linux-x64": "1.10.4",
|
package/src/main.js
CHANGED
|
@@ -1095,34 +1095,26 @@ electronApp.whenReady().then(async () => {
|
|
|
1095
1095
|
if (global.__cicyTitleSyncTimer.unref) global.__cicyTitleSyncTimer.unref();
|
|
1096
1096
|
}
|
|
1097
1097
|
|
|
1098
|
-
//
|
|
1099
|
-
//
|
|
1100
|
-
|
|
1098
|
+
// 窗口缩略图 & 桌面快照:默认**不再周期截图**(资源占用大头;消费端 cicy-code 已改
|
|
1099
|
+
// 用 live RPC /ui/snapshot 与按需 desktop_snapshot,见各文件)。改成「手动触发→按需截」:
|
|
1100
|
+
// - 窗口截图:cicy-code 走 electron_tab_screenshot / Page.captureScreenshot(live)
|
|
1101
|
+
// - 桌面截图:desktop_snapshot 工具按需截(win=一次性 --disable-gpu 子进程,mac/linux=live)
|
|
1102
|
+
// 想恢复后台常驻连续截图(给一直盯屏幕的 agent)再用 CICY_DESKTOP_SNAPSHOT=1 显式开。
|
|
1103
|
+
if (process.env.CICY_DESKTOP_SNAPSHOT === "1" && !global.__cicyDesktopSnapStarted) {
|
|
1104
|
+
global.__cicyDesktopSnapStarted = true;
|
|
1105
|
+
try {
|
|
1106
|
+
const info = require("./utils/desktop-snapshot").startDesktopSnapshots();
|
|
1107
|
+
log.info(`[desktop-snap] continuous desktop snapshots → ${info.dir} (every ${info.intervalMs}ms, mode ${info.mode})`);
|
|
1108
|
+
} catch (e) { log.warn(`[desktop-snap] start failed: ${e.message}`); }
|
|
1109
|
+
}
|
|
1110
|
+
if (process.env.CICY_WINDOW_THUMBS === "1" && !global.__cicyThumbStarted) {
|
|
1101
1111
|
global.__cicyThumbStarted = true;
|
|
1102
1112
|
try {
|
|
1103
1113
|
const info = require("./utils/window-thumbnails").startWindowThumbnails();
|
|
1104
|
-
log.info(`[thumbs] window thumbnails → ${info.dir} (every ${info.intervalMs}ms
|
|
1114
|
+
log.info(`[thumbs] window thumbnails → ${info.dir} (every ${info.intervalMs}ms)`);
|
|
1105
1115
|
} catch (e) { log.warn(`[thumbs] start failed: ${e.message}`); }
|
|
1106
1116
|
}
|
|
1107
1117
|
|
|
1108
|
-
// Periodic WHOLE-desktop snapshot → ~/cicy-files/desktop-snapshot/desktop.b64
|
|
1109
|
-
// so the cloud (cicy-code) can read the screen via the `desktop_snapshot` tool.
|
|
1110
|
-
// Windows uses a --disable-gpu child (GDI, no prompt); linux uses scrot.
|
|
1111
|
-
//
|
|
1112
|
-
// macOS: this spawns `screencapture`, which DOES trigger the Screen-Recording TCC
|
|
1113
|
-
// prompt — and on an ad-hoc-signed build (no Apple cert) the grant never sticks, so
|
|
1114
|
-
// the prompt fires over and over. So it's OFF by default on macOS (most users —
|
|
1115
|
-
// docker/team management — don't need the agent to watch their screen). Opt in with
|
|
1116
|
-
// CICY_DESKTOP_SNAPSHOT=1. Other platforms stay on (opt out with =0).
|
|
1117
|
-
const __snap = require("./utils/desktop-snapshot");
|
|
1118
|
-
if (!global.__cicyDesktopSnapStarted && __snap.snapshotEnabled()) {
|
|
1119
|
-
global.__cicyDesktopSnapStarted = true;
|
|
1120
|
-
try {
|
|
1121
|
-
const info = __snap.startDesktopSnapshots();
|
|
1122
|
-
log.info(`[desktop-snap] desktop snapshots → ${info.dir} (every ${info.intervalMs}ms, maxW ${info.maxWidth}, mode ${info.mode})`);
|
|
1123
|
-
} catch (e) { log.warn(`[desktop-snap] start failed: ${e.message}`); }
|
|
1124
|
-
}
|
|
1125
|
-
|
|
1126
1118
|
// Local-team discovery — reads ~/cicy-ai/global.json's cicyDesktopNodes
|
|
1127
1119
|
// and probes each via /api/health. Pure local, never talks to the cloud
|
|
1128
1120
|
// and never runs docker shells.
|
|
@@ -54,6 +54,7 @@ module.exports = (registerTool) => {
|
|
|
54
54
|
// BUT honor snapshotEnabled(): on macOS capture is off by default, and a live
|
|
55
55
|
// `screencapture` here is exactly what pops the Screen-Recording prompt (just
|
|
56
56
|
// less often than the daemon did) — so when disabled we must NOT live-capture.
|
|
57
|
+
// mac/linux:进程内即时抓屏(honor snapshotEnabled — mac 默认关避免授权弹窗)。
|
|
57
58
|
if (process.platform !== "win32" && snap.snapshotEnabled()) {
|
|
58
59
|
try {
|
|
59
60
|
const r = await snap.captureB64(maxWidth);
|
|
@@ -63,12 +64,25 @@ module.exports = (registerTool) => {
|
|
|
63
64
|
throw e;
|
|
64
65
|
}
|
|
65
66
|
}
|
|
67
|
+
// win32:进程内截不了(需 --disable-gpu)。按需起一个一次性 --disable-gpu 子进程
|
|
68
|
+
// 截一张、写盘,再读回来 —— 这样没有常驻 daemon 也能手动截图(手动触发→写盘→拉图)。
|
|
69
|
+
if (process.platform === "win32") {
|
|
70
|
+
try {
|
|
71
|
+
await snap.captureOnceWin();
|
|
72
|
+
const after = readDaemonB64();
|
|
73
|
+
if (after) return { content: [{ type: "text", text: after.b64 }] };
|
|
74
|
+
} catch (e) {
|
|
75
|
+
if (fresh) return { content: [{ type: "text", text: fresh.b64 }] };
|
|
76
|
+
throw e;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
66
79
|
|
|
67
80
|
if (fresh) return { content: [{ type: "text", text: fresh.b64 }] }; // stale is better than nothing
|
|
81
|
+
// macOS 默认关(避免反复弹屏幕录制授权)。
|
|
68
82
|
if (process.platform === "darwin" && !snap.snapshotEnabled()) {
|
|
69
|
-
throw new Error("桌面截图在 macOS 默认关闭(避免反复弹屏幕录制授权)。需要 agent 看屏幕时,启动 app
|
|
83
|
+
throw new Error("桌面截图在 macOS 默认关闭(避免反复弹屏幕录制授权)。需要 agent 看屏幕时,启动 app 前设环境变量 CICY_DESKTOP_SNAPSHOT=1。");
|
|
70
84
|
}
|
|
71
|
-
throw new Error("no desktop snapshot yet
|
|
85
|
+
throw new Error("no desktop snapshot yet");
|
|
72
86
|
} catch (error) {
|
|
73
87
|
return { content: [{ type: "text", text: `Error: ${error.message}` }], isError: true };
|
|
74
88
|
}
|
|
@@ -26,7 +26,7 @@ const electron = require("electron");
|
|
|
26
26
|
|
|
27
27
|
const MAX_W = 600; // 压到 600 以下宽度
|
|
28
28
|
const QUALITY = 60;
|
|
29
|
-
const DEFAULT_INTERVAL_MS =
|
|
29
|
+
const DEFAULT_INTERVAL_MS = 30000; // 8s→30s:降全屏截图频率(资源占用)
|
|
30
30
|
|
|
31
31
|
function snapDir() {
|
|
32
32
|
const fromEnv = (process.env.CICY_DESKTOP_SNAP_DIR || "").trim();
|
|
@@ -35,13 +35,16 @@ function snapDir() {
|
|
|
35
35
|
|
|
36
36
|
// Is desktop screen capture allowed here? Single source of truth shared by the
|
|
37
37
|
// periodic daemon (main.js) AND the on-demand `desktop_snapshot` tool's live fallback.
|
|
38
|
-
// OFF by default on macOS
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
//
|
|
38
|
+
// OFF by default on macOS AND Windows (opt in with CICY_DESKTOP_SNAPSHOT=1):
|
|
39
|
+
// - macOS: any capture trips the Screen-Recording prompt that won't persist for a
|
|
40
|
+
// non-Apple-Team-ID signature (re-prompts forever).
|
|
41
|
+
// - Windows: the periodic whole-desktop capture spawns an always-on --disable-gpu
|
|
42
|
+
// child + writes every 30s — pure overhead for users who only manage docker/teams
|
|
43
|
+
// and aren't being driven by a screen-watching cloud agent (资源占用). The on-demand
|
|
44
|
+
// `desktop_snapshot` tool still has its own live fallback when actually requested.
|
|
45
|
+
// linux stays ON by default (no prompt, cheap scrot); opt out with =0.
|
|
43
46
|
function snapshotEnabled() {
|
|
44
|
-
return process.platform === "darwin"
|
|
47
|
+
return (process.platform === "darwin" || process.platform === "win32")
|
|
45
48
|
? process.env.CICY_DESKTOP_SNAPSHOT === "1"
|
|
46
49
|
: process.env.CICY_DESKTOP_SNAPSHOT !== "0";
|
|
47
50
|
}
|
|
@@ -169,6 +172,29 @@ function stopDesktopSnapshots() {
|
|
|
169
172
|
if (child) { try { child.kill(); } catch (_) {} child = null; }
|
|
170
173
|
}
|
|
171
174
|
|
|
175
|
+
// On-demand ONE-SHOT capture (no persistent daemon). win32: spawn a --disable-gpu
|
|
176
|
+
// child that captures once, writes desktop.b64, and exits — so manual「立即截图」
|
|
177
|
+
// works without the periodic daemon running. mac/linux: capture in-process once.
|
|
178
|
+
// Resolves after the file is written; rejects on timeout/error.
|
|
179
|
+
function captureOnceWin(timeoutMs = 20000) {
|
|
180
|
+
if (process.platform !== "win32") return captureOnce();
|
|
181
|
+
return new Promise((resolve, reject) => {
|
|
182
|
+
const dir = snapDir();
|
|
183
|
+
try { fs.mkdirSync(dir, { recursive: true }); } catch (_) {}
|
|
184
|
+
let c;
|
|
185
|
+
try {
|
|
186
|
+
c = spawn(process.execPath, ["--disable-gpu", "--disable-logging", __filename], {
|
|
187
|
+
env: { ...process.env, CICY_SNAP_DAEMON: "1", CICY_SNAP_ONESHOT: "1" },
|
|
188
|
+
stdio: "ignore",
|
|
189
|
+
windowsHide: true,
|
|
190
|
+
});
|
|
191
|
+
} catch (e) { return reject(e); }
|
|
192
|
+
const timer = setTimeout(() => { try { c.kill(); } catch (_) {} reject(new Error("oneshot capture timeout")); }, timeoutMs);
|
|
193
|
+
c.on("exit", (code) => { clearTimeout(timer); resolve({ dir, code }); });
|
|
194
|
+
c.on("error", (e) => { clearTimeout(timer); reject(e); });
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
172
198
|
// ── daemon mode ───────────────────────────────────────────────────────────────
|
|
173
199
|
// Entered when this file is the entry of `electron --disable-gpu
|
|
174
200
|
// desktop-snapshot.js` (Windows capture child). Detected purely via the env flag
|
|
@@ -190,7 +216,13 @@ if (process.env.CICY_SNAP_DAEMON === "1") {
|
|
|
190
216
|
}
|
|
191
217
|
};
|
|
192
218
|
console.error("[snap-daemon] booting, dir=" + snapDir());
|
|
193
|
-
app.whenReady().then(() => {
|
|
219
|
+
app.whenReady().then(async () => {
|
|
220
|
+
// ONESHOT:截一张、写盘、退出(给 captureOnceWin 的按需手动截图用,不常驻)。
|
|
221
|
+
if (process.env.CICY_SNAP_ONESHOT === "1") {
|
|
222
|
+
await once();
|
|
223
|
+
try { app.quit(); } catch (_) {}
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
194
226
|
once();
|
|
195
227
|
const t = setInterval(once, intervalMs());
|
|
196
228
|
if (t.unref) t.unref();
|
|
@@ -200,4 +232,4 @@ if (process.env.CICY_SNAP_DAEMON === "1") {
|
|
|
200
232
|
app.on("render-process-gone", () => app.quit());
|
|
201
233
|
}
|
|
202
234
|
|
|
203
|
-
module.exports = { startDesktopSnapshots, stopDesktopSnapshots, snapDir, captureOnce, captureB64, snapshotEnabled, MAX_W };
|
|
235
|
+
module.exports = { startDesktopSnapshots, stopDesktopSnapshots, snapDir, captureOnce, captureOnceWin, captureB64, snapshotEnabled, MAX_W };
|
|
@@ -88,6 +88,10 @@ async function tick(opts) {
|
|
|
88
88
|
const manifest = [];
|
|
89
89
|
for (const win of wins) {
|
|
90
90
|
try {
|
|
91
|
+
// 跳过最小化/隐藏的窗口:capturePage 即使对不可见窗口也强制离屏重绘+GPU 回读
|
|
92
|
+
// (高占用主因)。看不见的没必要刷预览,留用上次的缩略图即可。
|
|
93
|
+
if (win.isMinimized && win.isMinimized()) continue;
|
|
94
|
+
if (win.isVisible && !win.isVisible()) continue;
|
|
91
95
|
const entry = await captureOne(win, dir, opts);
|
|
92
96
|
if (entry) manifest.push(entry);
|
|
93
97
|
} catch (_) {
|
|
@@ -104,7 +108,7 @@ async function tick(opts) {
|
|
|
104
108
|
|
|
105
109
|
function startWindowThumbnails(options = {}) {
|
|
106
110
|
const opts = {
|
|
107
|
-
intervalMs: options.intervalMs ||
|
|
111
|
+
intervalMs: options.intervalMs || 20000, // 4s→20s:降 capturePage 频率(资源占用大头)
|
|
108
112
|
maxWidth: options.maxWidth || 320, // small rect, chrome-ish
|
|
109
113
|
quality: options.quality || 60,
|
|
110
114
|
};
|