cicy-desktop 2.1.254 → 2.1.256

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.254",
3
+ "version": "2.1.256",
4
4
  "description": "CiCy - AI-powered operating system browser",
5
5
  "main": "src/main.js",
6
6
  "bin": {
@@ -139,10 +139,10 @@
139
139
  "//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 着无害。",
140
140
  "optionalDependencies": {
141
141
  "electron": "41.0.3",
142
- "cicy-code-darwin-x64": "2.3.311",
143
- "cicy-code-darwin-arm64": "2.3.311",
144
- "cicy-code-linux-x64": "2.3.311",
145
- "cicy-code-linux-arm64": "2.3.311",
142
+ "cicy-code-darwin-x64": "2.3.315",
143
+ "cicy-code-darwin-arm64": "2.3.315",
144
+ "cicy-code-linux-x64": "2.3.315",
145
+ "cicy-code-linux-arm64": "2.3.315",
146
146
  "cicy-code-windows-x64": "2.3.193",
147
147
  "cicy-mihomo-darwin-x64": "1.10.4",
148
148
  "cicy-mihomo-darwin-arm64": "1.10.4",
@@ -150,13 +150,24 @@ function register({ sidecarLogPath } = {}) {
150
150
  _dockerDaemonBusy = true;
151
151
  try {
152
152
  const s = await refreshDockerStatus();
153
- // 没启动的给我启动: distro installed but :8008 not healthy (and WSL not unknown)
154
- // → bring it up. bootstrap is idempotent: it skips done steps and just runs
155
- // startEngine + the container. Skip when not installed (would silently pull
156
- // the 444MB rootfs) or unknown (WSL not answering — let the next tick retry).
157
- if (s.installed && !s.running && !s.unknown) {
158
- log.info("[docker-daemon] installed but :8008 down → auto-starting (bootstrap idempotent)");
159
- try { await appDocker.bootstrap(await appOpts()); } catch (e) { log.warn(`[docker-daemon] auto-start failed: ${e.message}`); }
153
+ // 打开 cicy-desktop 就保证 Windows/WSL :8008 可用:
154
+ // - 已安装但停止 启动 WSL、dockerd 和容器;
155
+ // - 从未安装 bootstrap 自动启用 WSL2、导入专用 distro、安装 Docker
156
+ // Engine、拉取镜像并启动 cicy-code。
157
+ // bootstrap 幂等且可续跑;首次启用 WSL 若要求重启 Windows,下次登录 Desktop
158
+ // 会再次进入这里并从已完成的步骤继续。unknown 表示 WSL 正卡住/未响应,
159
+ // 此时不并发安装,留给下一轮检测或显式「修复 WSL」。
160
+ if (!s.running && !s.unknown) {
161
+ log.info(`[docker-daemon] :8008 down (${s.installed ? "installed" : "not installed"}) → auto-bootstrapping WSL cicy-code`);
162
+ try {
163
+ await ensureDockerTeam().catch(() => {});
164
+ const result = await appDocker.bootstrap(await appOpts());
165
+ if (result && result.ok) {
166
+ try { await registerAppTeam(); } catch {}
167
+ } else if (result && result.reason) {
168
+ log.warn(`[docker-daemon] auto-bootstrap paused: ${result.reason}`);
169
+ }
170
+ } catch (e) { log.warn(`[docker-daemon] auto-bootstrap failed: ${e.message}`); }
160
171
  await refreshDockerStatus();
161
172
  } else if (s.running) {
162
173
  // 自愈:容器在跑,但很可能是「首次启动时还没登录 / key 还没就位就建好了」的没 key 容器
package/src/main.js CHANGED
@@ -939,30 +939,39 @@ electronApp.whenReady().then(async () => {
939
939
  const lt = require("./backends/local-teams");
940
940
 
941
941
  // 占位卡("先有一个 :8008 占位"): 开机**立刻无条件**注册本地团队,homepage 永远有
942
- // 这张卡 —— :8008 没起来时显示「未运行」+ 启动/安装入口(不会再空首页);起来后下面的
943
- // probe 循环 upsert 一次,状态翻 running + 触发 gateway key/teamId 注入。addTeam 幂等。
942
+ // 这张卡 —— :8008 启动期间显示「未运行」;起来后下面的自动启动流程 upsert 一次,
943
+ // 状态翻 running + 触发 gateway key/teamId 注入。addTeam 幂等。
944
944
  lt.addTeam({ base_url: `http://127.0.0.1:${sidecarPort}`, name: i18n.t("localTeams.defaultName") })
945
945
  .then((r) => { if (r && r.id) log.info(`[Sidecar] local team placeholder registered (${r.id})`); })
946
946
  .catch((e) => log.warn(`[Sidecar] placeholder register failed: ${e.message}`));
947
947
 
948
- // **不在 boot 静默 start**(bug 修复): 首次启动要装 Node/brew/tmux 等依赖,必须让
949
- // 用户在点「启动并打开」时**看着 drawer 装**(命令/进度/错误/重试)。boot 静默装会:① 用户
950
- // 看不到卡在哪 ② 和用户点击重复 spawn 抢锁。所以这里只:① 注册占位卡 若 cicy-code 已在
951
- // 跑(上次保活留下的)就 adopt 刷新状态 + 拿 key/teamId。真正的启动/安装由 sidecar:start
952
- // (点「启动并打开」)驱动,带 drawer。
948
+ // 打开 cicy-desktop 就保证本地 :8008 自动启动。start() 自带 child 去重:
949
+ // 自动启动仍在准备依赖时,用户点击「启动并打开」只会复用同一个 child,不会重复
950
+ // spawn 或抢安装锁。若上次退出后 daemon 仍在,则直接 adopt,不启动第二份。
953
951
  (async () => {
954
- for (let i = 0; i < 40; i++) {
955
- try {
956
- if (await cicyCodeSidecar.probeExisting(sidecarPort)) {
957
- const r = await lt.addTeam({ base_url: `http://127.0.0.1:${sidecarPort}`, name: i18n.t("localTeams.defaultName") });
958
- if (r && r.id) log.info(`[Sidecar] adopted running cicy-code → local team ready (${r.id})`);
959
- startSidecarWatchdog(); // 已在跑 → 起 watchdog 保活(崩了重起,此时依赖已装、起得快)
960
- return;
952
+ try {
953
+ let running = await cicyCodeSidecar.probeExisting(sidecarPort);
954
+ if (!running) {
955
+ log.info(`[Sidecar] :${sidecarPort} 未运行 随 cicy-desktop 自动启动`);
956
+ await cicyCodeSidecar.start({
957
+ logPath: path.join(os.homedir(), "logs", "cicy-code-sidecar.log"),
958
+ });
959
+ // 首次启动可能要准备运行环境和恢复 agent 面板;等待端口真正监听。
960
+ for (let i = 0; i < 360 && !running; i++) {
961
+ await new Promise((res) => setTimeout(res, 500));
962
+ running = await cicyCodeSidecar.probeExisting(sidecarPort);
961
963
  }
962
- } catch (e) { log.warn(`[Sidecar] adopt probe error: ${e.message}`); }
963
- await new Promise((res) => setTimeout(res, 3000));
964
+ }
965
+ if (!running) {
966
+ log.warn(`[Sidecar] 自动启动后 :${sidecarPort} 在 180s 内仍未就绪`);
967
+ return;
968
+ }
969
+ const r = await lt.addTeam({ base_url: `http://127.0.0.1:${sidecarPort}`, name: i18n.t("localTeams.defaultName") });
970
+ if (r && r.id) log.info(`[Sidecar] running cicy-code adopted → local team ready (${r.id})`);
971
+ startSidecarWatchdog();
972
+ } catch (e) {
973
+ log.warn(`[Sidecar] 自动启动失败: ${e.message}`);
964
974
  }
965
- log.info(`[Sidecar] :${sidecarPort} 未在跑 — 占位卡显示「未运行」,等用户点「启动并打开」(带安装 drawer)`);
966
975
  })();
967
976
  }
968
977
 
@@ -136,10 +136,16 @@ class PanelCells {
136
136
  const push = () => {
137
137
  let url = "", title = "";
138
138
  try { url = wc.getURL(); title = wc.getTitle(); } catch (e) {}
139
- this.sendState({ id: cellId, url, title, loading: false, wcId: wc.id });
139
+ // did-navigate / page-title-updated commonly fire while the document is
140
+ // still loading. Hard-coding false here hid the spinner immediately after
141
+ // did-start-loading; report the BrowserView's actual state instead.
142
+ let loading = false;
143
+ try { loading = wc.isLoading(); } catch (e) {}
144
+ this.sendState({ id: cellId, url, title, loading, wcId: wc.id });
140
145
  };
141
146
  wc.on("did-start-loading", () => this.sendState({ id: cellId, loading: true, wcId: wc.id }));
142
147
  wc.on("did-stop-loading", push);
148
+ wc.on("did-fail-load", push);
143
149
  wc.on("did-navigate", push);
144
150
  wc.on("did-navigate-in-page", push);
145
151
  wc.on("page-title-updated", push);
@@ -26,8 +26,12 @@
26
26
  .native-cells .cell,.native-cells .divider{transition:none}
27
27
  .cell.dragging-layout{transition:none}
28
28
  .cell__head{flex:0 0 34px;display:flex;align-items:center;gap:6px;padding:0 6px 0 10px;background:var(--head);border-bottom:1px solid var(--line);-webkit-user-select:none;user-select:none}
29
- .cell__spin{flex:0 0 12px;width:12px;height:12px;border:2px solid rgba(255,255,255,.18);border-top-color:var(--accent);border-radius:50%;animation:sp .7s linear infinite;display:none}
30
- .cell.loading .cell__spin{display:block}
29
+ /* Reload and loading share one fixed button slot: loading swaps the glyph in
30
+ place, so no toolbar element moves and no extra padding is needed. */
31
+ .reload-btn{position:relative}
32
+ .reload-btn .cell__spin{position:absolute;width:12px;height:12px;border:2px solid rgba(255,255,255,.18);border-top-color:var(--accent);border-radius:50%;animation:sp .7s linear infinite;visibility:hidden}
33
+ .cell.loading .reload-btn>svg{visibility:hidden}
34
+ .cell.loading .reload-btn .cell__spin{visibility:visible}
31
35
  @keyframes sp{to{transform:rotate(360deg)}}
32
36
  .cell__url{flex:1;min-width:0;height:24px;padding:0 10px;background:#101012;border:1px solid var(--line);border-radius:12px;color:var(--fg);font-size:12px;outline:none;-webkit-user-select:text;user-select:text}
33
37
  .cell__url:focus{border-color:var(--accent);background:#0d0d10}
@@ -639,18 +643,25 @@
639
643
  url.value = leaf.url || '';
640
644
  url.addEventListener('keydown', (e) => {
641
645
  if (e.key !== 'Enter') return;
646
+ // Enter during an IME composition commits the composing text; navigating
647
+ // and blurring in that same event makes Chromium commit it a second time
648
+ // (e.g. "chatgpt" → "chatgptchatgpt"). Let the IME finish first; the
649
+ // following Enter performs navigation, matching a normal browser omnibox.
650
+ if (e.isComposing || e.keyCode === 229) return;
651
+ e.preventDefault();
642
652
  const u = normalizeUrl(url.value);
643
653
  if (u) { setCellUrl(leaf.id, u); url.blur(); }
644
654
  });
645
655
  url.addEventListener('focus', () => url.select());
646
- head.appendChild(spin);
647
656
  head.appendChild(service);
648
657
  head.appendChild(profile);
649
658
  head.appendChild(url);
650
- head.appendChild(btn(I.reload, '刷新', '', () => {
659
+ const reload = btn(I.reload, '刷新', 'reload-btn', () => {
651
660
  if (NATIVE) { try { window.panelAPI.reload(leaf.id); } catch (e) {} return; }
652
661
  const c = cells.get(leaf.id); try { c && c.wv && c.wv.reload(); } catch (e) {}
653
- }));
662
+ });
663
+ reload.appendChild(spin);
664
+ head.appendChild(reload);
654
665
  head.appendChild(btn(I.splitR, '右分屏', '', () => splitLeaf(leaf.id, 'row')));
655
666
  head.appendChild(btn(I.splitD, '下分屏', '', () => splitLeaf(leaf.id, 'col')));
656
667
  head.appendChild(btn(I.close, '关闭', 'close', () => closeLeaf(leaf.id)));