cicy-desktop 2.1.273 → 2.1.274
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
|
@@ -52,11 +52,13 @@ module.exports = (registerTool) => {
|
|
|
52
52
|
return { content: [{ type: "text", text: fresh.b64 }] };
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
// Stale/missing.
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
|
|
55
|
+
// Stale/missing. mac/linux can capture live in-process; win32 cannot (needs
|
|
56
|
+
// the --disable-gpu daemon), so there we fall back to whatever file exists.
|
|
57
|
+
// BUT honor snapshotEnabled(): on macOS capture is off by default, and a live
|
|
58
|
+
// `screencapture` here is exactly what pops the Screen-Recording prompt (just
|
|
59
|
+
// less often than the daemon did) — so when disabled we must NOT live-capture.
|
|
60
|
+
// mac/linux:进程内即时抓屏(honor snapshotEnabled — mac 默认关避免授权弹窗)。
|
|
61
|
+
if (process.platform !== "win32" && snap.snapshotEnabled()) {
|
|
60
62
|
try {
|
|
61
63
|
const r = await snap.captureB64(maxWidth);
|
|
62
64
|
return { content: [{ type: "text", text: r.b64 }] };
|
|
@@ -79,6 +81,10 @@ module.exports = (registerTool) => {
|
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
if (fresh) return { content: [{ type: "text", text: fresh.b64 }] }; // stale is better than nothing
|
|
84
|
+
// macOS 默认关(避免反复弹屏幕录制授权)。
|
|
85
|
+
if (process.platform === "darwin" && !snap.snapshotEnabled()) {
|
|
86
|
+
throw new Error("桌面截图在 macOS 默认关闭(避免反复弹屏幕录制授权)。需要 agent 看屏幕时,启动 app 前设环境变量 CICY_DESKTOP_SNAPSHOT=1。");
|
|
87
|
+
}
|
|
82
88
|
throw new Error("no desktop snapshot yet");
|
|
83
89
|
} catch (error) {
|
|
84
90
|
return { content: [{ type: "text", text: `Error: ${error.message}` }], isError: true };
|
|
@@ -37,15 +37,14 @@ function snapDir() {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
// Is desktop screen capture allowed here? Single source of truth shared by the
|
|
40
|
-
// periodic daemon (main.js)
|
|
41
|
-
// switch: clicking “立即截图” must work without enabling background capture.
|
|
40
|
+
// periodic daemon (main.js) AND the on-demand `desktop_snapshot` tool's live fallback.
|
|
42
41
|
// OFF by default on macOS AND Windows (opt in with CICY_DESKTOP_SNAPSHOT=1):
|
|
43
42
|
// - macOS: any capture trips the Screen-Recording prompt that won't persist for a
|
|
44
43
|
// non-Apple-Team-ID signature (re-prompts forever).
|
|
45
44
|
// - Windows: the periodic whole-desktop capture spawns an always-on --disable-gpu
|
|
46
45
|
// child + writes every 30s — pure overhead for users who only manage docker/teams
|
|
47
46
|
// and aren't being driven by a screen-watching cloud agent (资源占用). The on-demand
|
|
48
|
-
// `desktop_snapshot` still
|
|
47
|
+
// `desktop_snapshot` tool still has its own live fallback when actually requested.
|
|
49
48
|
// linux stays ON by default (no prompt, cheap scrot); opt out with =0.
|
|
50
49
|
function snapshotEnabled() {
|
|
51
50
|
return (process.platform === "darwin" || process.platform === "win32")
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Copyright 2026 CiCy AI
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
const assert = require("node:assert/strict");
|
|
5
|
+
const fs = require("node:fs");
|
|
6
|
+
const os = require("node:os");
|
|
7
|
+
const path = require("node:path");
|
|
8
|
+
const test = require("node:test");
|
|
9
|
+
|
|
10
|
+
test("desktop_snapshot does not capture live when desktop snapshots are disabled", async (t) => {
|
|
11
|
+
if (process.platform === "win32") {
|
|
12
|
+
t.skip("the Windows one-shot capture path is intentionally separate");
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const emptySnapshotDir = fs.mkdtempSync(path.join(os.tmpdir(), "cicy-snapshot-test-"));
|
|
17
|
+
t.after(() => fs.rmSync(emptySnapshotDir, { recursive: true, force: true }));
|
|
18
|
+
|
|
19
|
+
const snapshotPath = require.resolve("../src/utils/desktop-snapshot");
|
|
20
|
+
const toolsPath = require.resolve("../src/tools/desktop-snapshot-tools");
|
|
21
|
+
const originalSnapshotModule = require.cache[snapshotPath];
|
|
22
|
+
const originalToolsModule = require.cache[toolsPath];
|
|
23
|
+
let captureCalls = 0;
|
|
24
|
+
|
|
25
|
+
require.cache[snapshotPath] = {
|
|
26
|
+
id: snapshotPath,
|
|
27
|
+
filename: snapshotPath,
|
|
28
|
+
loaded: true,
|
|
29
|
+
exports: {
|
|
30
|
+
snapDir: () => emptySnapshotDir,
|
|
31
|
+
snapshotEnabled: () => false,
|
|
32
|
+
captureB64: async () => {
|
|
33
|
+
captureCalls += 1;
|
|
34
|
+
return { b64: "captured" };
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
delete require.cache[toolsPath];
|
|
39
|
+
|
|
40
|
+
t.after(() => {
|
|
41
|
+
if (originalSnapshotModule) require.cache[snapshotPath] = originalSnapshotModule;
|
|
42
|
+
else delete require.cache[snapshotPath];
|
|
43
|
+
if (originalToolsModule) require.cache[toolsPath] = originalToolsModule;
|
|
44
|
+
else delete require.cache[toolsPath];
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
let handler;
|
|
48
|
+
require(toolsPath)((name, _description, _schema, registeredHandler) => {
|
|
49
|
+
if (name === "desktop_snapshot") handler = registeredHandler;
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
assert.equal(typeof handler, "function");
|
|
53
|
+
const result = await handler({ maxWidth: 600 });
|
|
54
|
+
|
|
55
|
+
assert.equal(captureCalls, 0);
|
|
56
|
+
assert.equal(result.isError, true);
|
|
57
|
+
assert.match(result.content[0].text, /^Error:/);
|
|
58
|
+
});
|