cicy-desktop 2.1.273 → 2.1.275

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.
@@ -67,7 +67,7 @@ jobs:
67
67
  - name: Build Linux AppImage
68
68
  shell: bash
69
69
  env:
70
- GH_TOKEN: ${{ secrets.CICY_RELEASE_GH_TOKEN }}
70
+ GH_TOKEN: ${{ github.token }}
71
71
  CICY_OBFUSCATE: "1" # 发版混淆 JS(prebuild 主进程 + Vite 渲染层),仅 release CI
72
72
  run: |
73
73
  set -euo pipefail
@@ -110,7 +110,7 @@ jobs:
110
110
  shell: bash
111
111
  env:
112
112
  CSC_IDENTITY_AUTO_DISCOVERY: "false"
113
- GH_TOKEN: ${{ secrets.CICY_RELEASE_GH_TOKEN }}
113
+ GH_TOKEN: ${{ github.token }}
114
114
  CICY_OBFUSCATE: "1" # 发版混淆 JS(prebuild 主进程 + Vite 渲染层),仅 release CI
115
115
  run: |
116
116
  set -euo pipefail
@@ -136,7 +136,7 @@ jobs:
136
136
  - name: Ensure draft GitHub release exists
137
137
  shell: bash
138
138
  env:
139
- GH_TOKEN: ${{ secrets.CICY_RELEASE_GH_TOKEN }}
139
+ GH_TOKEN: ${{ github.token }}
140
140
  run: |
141
141
  gh release create "${{ steps.meta.outputs.tag }}" \
142
142
  --repo "cicy-ai/cicy-desktop" \
@@ -148,7 +148,7 @@ jobs:
148
148
  - name: Build and publish PKG installers
149
149
  shell: bash
150
150
  env:
151
- GH_TOKEN: ${{ secrets.CICY_RELEASE_GH_TOKEN }}
151
+ GH_TOKEN: ${{ github.token }}
152
152
  run: |
153
153
  set -euo pipefail
154
154
  VER="${{ steps.meta.outputs.version }}"
@@ -72,7 +72,7 @@ jobs:
72
72
  # uploaded. Promoted to non-draft + latest in the final step.
73
73
  shell: bash
74
74
  env:
75
- GH_TOKEN: ${{ secrets.CICY_RELEASE_GH_TOKEN }}
75
+ GH_TOKEN: ${{ github.token }}
76
76
  run: |
77
77
  gh release create "${{ steps.meta.outputs.tag }}" \
78
78
  --repo "cicy-ai/cicy-desktop" \
@@ -85,7 +85,7 @@ jobs:
85
85
  # --publish always uploads .exe + latest.yml to the release created above.
86
86
  shell: powershell
87
87
  env:
88
- GH_TOKEN: ${{ secrets.CICY_RELEASE_GH_TOKEN }}
88
+ GH_TOKEN: ${{ github.token }}
89
89
  CICY_OBFUSCATE: "1" # 发版混淆 JS(prebuild 主进程 + Vite 渲染层),仅 release CI
90
90
  run: |
91
91
  if (Test-Path dist) { Remove-Item -Recurse -Force dist }
@@ -176,7 +176,7 @@ jobs:
176
176
  # existing clients will pick up the new version on its next poll.
177
177
  shell: bash
178
178
  env:
179
- GH_TOKEN: ${{ secrets.CICY_RELEASE_GH_TOKEN }}
179
+ GH_TOKEN: ${{ github.token }}
180
180
  run: |
181
181
  gh release edit "${{ steps.meta.outputs.tag }}" \
182
182
  --repo "cicy-ai/cicy-desktop" \
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cicy-desktop",
3
- "version": "2.1.273",
3
+ "version": "2.1.275",
4
4
  "description": "CiCy - AI-powered operating system browser",
5
5
  "main": "src/main.js",
6
6
  "bin": {
@@ -52,11 +52,13 @@ module.exports = (registerTool) => {
52
52
  return { content: [{ type: "text", text: fresh.b64 }] };
53
53
  }
54
54
 
55
- // Stale/missing. A desktop_snapshot RPC is an explicit one-shot request,
56
- // so mac/linux capture immediately even when the periodic daemon is off.
57
- // CICY_DESKTOP_SNAPSHOT only controls the background capture loop in
58
- // main.js; it must not make the user's “立即截图” button unusable.
59
- if (process.platform !== "win32") {
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). One-shot `desktop_snapshot` RPC requests bypass this
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 captures once when explicitly requested.
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
+ });