cicy-desktop 2.1.166 → 2.1.168

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.
@@ -6,7 +6,7 @@
6
6
  <link rel="icon" type="image/svg+xml" href="./favicon.svg" />
7
7
  <link rel="icon" type="image/png" sizes="256x256" href="./favicon-256.png" />
8
8
  <title>CiCy Desktop</title>
9
- <script type="module" crossorigin src="./assets/index-C8HjxypR.js"></script>
9
+ <script type="module" crossorigin src="./assets/index-DczjleYe.js"></script>
10
10
  <link rel="stylesheet" crossorigin href="./assets/index-CGcN1St7.css">
11
11
  </head>
12
12
  <body>
@@ -46,24 +46,9 @@ const APP_PORT = Number(process.env.CICY_DOCKER_APP_PORT || 8009);
46
46
  const APP_CONTAINER = process.env.CICY_DOCKER_APP_CONTAINER || `cicy-code-docker-${APP_PORT}`;
47
47
  const APP_VOLUME = process.env.CICY_DOCKER_APP_VOLUME || `cicy-team-${APP_PORT}`;
48
48
  const APP_MOUNT = process.env.CICY_DOCKER_APP_MOUNT || "/home/cicy";
49
- // 8008 and 8009 are ONE team (主人), so :8009 reaches the LLM through the cicy
50
- // gateway using 8008's TEAM key the `sk-cicy-…` apiKey already minted in 8008's
51
- // global.json providers (NOT the api_token, which is only the local access
52
- // credential). 8008 is up by the time the Docker card is used, so the key is
53
- // ready — we just read it and pass it to the container. Same key ⇒ same billing.
49
+ // :8009 docker 的网关 endpoint。key 不再从 :8008 借(native 已退役)—— 容器只用它
50
+ // 自己独立云端 team key(见 ensureDockerTeam / appOpts)。
54
51
  const GATEWAY_ENDPOINT = process.env.CICY_AI_GATEWAY_LLM_ENDPOINT || "https://gateway.cicy-ai.com";
55
- function readLocalGatewayKey() {
56
- try {
57
- const p = path.join(os.homedir(), "cicy-ai", "global.json");
58
- const g = JSON.parse(fs.readFileSync(p, "utf8"));
59
- const items = (g.providers && g.providers.items) || [];
60
- const pick =
61
- items.find((it) => it && it.apiKey && String(it.url || "").includes("gateway.cicy-ai.com")) ||
62
- items.find((it) => it && it.key === "defaultAnthropic" && it.apiKey) ||
63
- items.find((it) => it && it.apiKey);
64
- return pick ? String(pick.apiKey || "") : "";
65
- } catch { return ""; }
66
- }
67
52
 
68
53
  // ── Docker 独立云端 team ──────────────────────────────────────────────────────
69
54
  // 主人令(2026-06-21):每个 Docker 容器要有自己独立的云端 team(8008 那个本机
@@ -80,7 +65,7 @@ let dockerTeamReg = null; // { teamId, title, apiKey } — 缓存,appOpts 读它
80
65
 
81
66
  // 确保这个 docker(按 volume)有独立云端 team;返回 { teamId, title, apiKey } 或 null。
82
67
  async function ensureDockerTeam() {
83
- if (!cc || !cc.loginToken || !cc.loginToken()) return null; // 未登录 → appOpts 回退 8008 key
68
+ if (!cc || !cc.loginToken || !cc.loginToken()) return null; // 未登录 → 先不带 key,登录后重建容器再补(绝不借 8008)
84
69
  try {
85
70
  const store = readDockerTeams();
86
71
  let rec = store[APP_VOLUME];
@@ -102,7 +87,20 @@ async function ensureDockerTeam() {
102
87
  rec.title = "Docker 团队"; rec.titleForced = true;
103
88
  store[APP_VOLUME] = rec; writeDockerTeams(store);
104
89
  }
90
+ // 「如果没有就 create,有就直接用」(主人)。本机记了 teamId,但云端拿不到它的 key
91
+ // (team 被删 / 换了账号 / 设备重置 —— 等于实际上没有了)→ 视同没有,重新 create 一个
92
+ // 存回本机。这就是手动「清 docker-teams.json + 重建」做的事,自动化掉。
105
93
  const apiKey = await cc.getTeamApiKey(rec.teamId);
94
+ if (!apiKey) {
95
+ const created = await cc.createTeam({ title: "Docker 团队", kind: "cloud" });
96
+ if (created && created.ok) {
97
+ try { await cc.renameTeam(created.teamId, "Docker 团队"); } catch {}
98
+ store[APP_VOLUME] = { teamId: created.teamId, title: "Docker 团队", titleForced: true };
99
+ writeDockerTeams(store);
100
+ dockerTeamReg = { teamId: created.teamId, title: "Docker 团队", apiKey: created.apiKey };
101
+ return dockerTeamReg;
102
+ }
103
+ }
106
104
  dockerTeamReg = { teamId: rec.teamId, title: rec.title, apiKey };
107
105
  return dockerTeamReg;
108
106
  } catch (e) { return null; }
@@ -143,7 +141,7 @@ function register({ sidecarLogPath } = {}) {
143
141
  // the 444MB rootfs) or unknown (WSL not answering — let the next tick retry).
144
142
  if (s.installed && !s.running && !s.unknown) {
145
143
  log.info("[docker-daemon] installed but :8009 down → auto-starting (bootstrap idempotent)");
146
- try { await appDocker.bootstrap(appOpts()); } catch (e) { log.warn(`[docker-daemon] auto-start failed: ${e.message}`); }
144
+ try { await appDocker.bootstrap(await appOpts()); } catch (e) { log.warn(`[docker-daemon] auto-start failed: ${e.message}`); }
147
145
  await refreshDockerStatus();
148
146
  }
149
147
  } finally { _dockerDaemonBusy = false; }
@@ -234,15 +232,15 @@ function register({ sidecarLogPath } = {}) {
234
232
  return s;
235
233
  });
236
234
 
237
- // Common run options for the :8009 instance: its own container/volume + the
238
- // LLM gateway env keyed by the 8008 team's token. (WSL: whole-home mount via
239
- // -v <volume>:/home/cicy inside wsl-docker.)
240
- const appOpts = () => {
241
- // Docker 独立 team 的网关 key 优先(ensureDockerTeam 已缓存);未登录/未建成功
242
- // 时回退 8008 key,保证容器仍有 LLM key 可用。
243
- const gwKey = (dockerTeamReg && dockerTeamReg.apiKey) || readLocalGatewayKey();
235
+ // Common run options for the :8009 instance: its own container/volume + the LLM
236
+ // gateway env. 主人: :8009 必须用「它自己独立云端 team」的 key —— ensureDockerTeam
237
+ // 没建就建(createTeam),用那个 teamId key。绝不借别人的(native :8008 已退役,
238
+ // 没得借,也不许借)。所以 appOpts async:先 await ensureDockerTeam,确保容器启动
239
+ // 前自己的 key 已就位;拿不到(未登录)就先不带 key,登录后「重建 Docker」再带上。
240
+ const appOpts = async () => {
241
+ await ensureDockerTeam().catch(() => {});
244
242
  const env = { CICY_AI_GATEWAY_LLM_ENDPOINT: GATEWAY_ENDPOINT };
245
- if (gwKey) env.CICY_AI_GATEWAY_LLM_API_KEY = gwKey;
243
+ if (dockerTeamReg && dockerTeamReg.apiKey) env.CICY_AI_GATEWAY_LLM_API_KEY = dockerTeamReg.apiKey;
246
244
  return { port: APP_PORT, container: APP_CONTAINER, volume: APP_VOLUME, env };
247
245
  };
248
246
  // Register the running :8009 instance as a (custom) team so the card's "打开"
@@ -303,7 +301,7 @@ function register({ sidecarLogPath } = {}) {
303
301
  try {
304
302
  await ensureDockerTeam(); // 启动前先确保独立云端 team + 拿到它的网关 key(appOpts 用)
305
303
  const result = await appDocker.bootstrap({
306
- ...appOpts(),
304
+ ...(await appOpts()),
307
305
  onProgress: (ev) => { try { e.sender.send("docker:app-progress", ev); } catch {} },
308
306
  });
309
307
  if (result && result.ok) await registerAppTeam();
@@ -330,7 +328,7 @@ function register({ sidecarLogPath } = {}) {
330
328
  ipcMain.handle("docker:app-recreate", async () => {
331
329
  try {
332
330
  await ensureDockerTeam();
333
- await appDocker.recreate({ ...appOpts() });
331
+ await appDocker.recreate({ ...(await appOpts()) });
334
332
  await registerAppTeam();
335
333
  return { ok: true };
336
334
  } catch (e) { return { ok: false, error: e.message }; }
@@ -360,7 +358,7 @@ function register({ sidecarLogPath } = {}) {
360
358
  try {
361
359
  await ensureDockerTeam();
362
360
  const result = await appDocker.upgrade({
363
- ...appOpts(),
361
+ ...(await appOpts()),
364
362
  onProgress: (ev) => { try { e.sender.send("docker:app-progress", ev); } catch {} },
365
363
  });
366
364
  if (result && result.ok) await registerAppTeam();
@@ -158,7 +158,8 @@
158
158
  "dockerRestart": "Restart Docker",
159
159
  "dockerRestarted": "Docker container restarted",
160
160
  "recreate": "Rebuild Docker",
161
- "billing": "Billing"
161
+ "billing": "Billing",
162
+ "openNoToken": "Service not ready yet — wait a few seconds and click Open again (or 「Restart」 from the card menu)."
162
163
  },
163
164
  "common": {
164
165
  "close": "Close",
@@ -157,7 +157,8 @@
157
157
  "dockerRestart": "Redémarrer Docker",
158
158
  "dockerRestarted": "Conteneur Docker redémarré",
159
159
  "recreate": "Reconstruire Docker",
160
- "billing": "Facturation"
160
+ "billing": "Facturation",
161
+ "openNoToken": "Service pas encore prêt — patientez quelques secondes puis recliquez sur Ouvrir (ou 「Redémarrer」 dans le menu)."
161
162
  },
162
163
  "common": {
163
164
  "close": "Fermer",
@@ -157,7 +157,8 @@
157
157
  "dockerRestart": "Docker を再起動",
158
158
  "dockerRestarted": "Docker コンテナを再起動しました",
159
159
  "recreate": "Docker を再構築",
160
- "billing": "請求"
160
+ "billing": "請求",
161
+ "openNoToken": "サービスがまだ準備できていません。数秒待ってから「開く」を再度クリック(またはカードメニューの「再起動」)。"
161
162
  },
162
163
  "common": {
163
164
  "close": "閉じる",
@@ -158,7 +158,8 @@
158
158
  "dockerRestart": "重启 Docker",
159
159
  "dockerRestarted": "已重启 Docker 容器",
160
160
  "recreate": "重建 Docker",
161
- "billing": "帐单"
161
+ "billing": "帐单",
162
+ "openNoToken": "服务还没就绪,稍等几秒再点「打开」(或用卡片菜单「重启」)。"
162
163
  },
163
164
  "common": {
164
165
  "close": "关闭",
package/src/main.js CHANGED
@@ -880,6 +880,21 @@ electronApp.whenReady().then(async () => {
880
880
  // 主人: native :8008 退役 —— 不再起本机 cicy-code、不再 watchdog 保活、不再把它
881
881
  // 自动注册成「本地团队」。cicy-code 只在 docker 容器里跑(Docker 卡,:8009 那套不变,
882
882
  // 由 sidecar-ipc 自己管理)。cicyCodeSidecar 仍保留供 :8008 探活/版本查询用。
883
+ //
884
+ // 升级清理:历史遗留的「本地团队」(http://127.0.0.1:8008)节点现在是死的(native 没了),
885
+ // 它那张连不上的卡得删掉。只删这个 native :8008 节点;docker :8009 + 自定义团队不动。
886
+ (async () => {
887
+ try {
888
+ const lt = require("./backends/local-teams");
889
+ const teams = await lt.list().catch(() => []);
890
+ for (const t of (teams || [])) {
891
+ if (/\/\/127\.0\.0\.1:8008(\/|$|\b)/.test(String(t.base_url || ""))) {
892
+ await lt.removeTeam(t.id).catch(() => {});
893
+ log.info(`[migrate] removed retired native :8008 team ${t.id}`);
894
+ }
895
+ }
896
+ } catch {}
897
+ })();
883
898
 
884
899
  // Backend launcher: app menu + IPC handlers. Menu adds a Backends top-level
885
900
  // entry; IPC powers the launcher window (src/backends/launcher.html).
@@ -847,7 +847,7 @@ export default function App() {
847
847
  // (主人: 必须拿到 token 才能打开,否则被卡在登录页).
848
848
  try {
849
849
  const r = await window.cicy?.docker?.appOpen?.();
850
- if (!r?.ok) window.alert("拿不到容器 token,无法打开 :8009。请确认服务已就绪(或用卡片菜单「重启」)后再试。");
850
+ if (!r?.ok) toast.show({ id: "docker-open", status: "error", ttl: 6000, message: tr("docker.openNoToken", "服务还没就绪,稍等几秒再点「打开」(或用卡片菜单「重启」)") });
851
851
  } catch (e) { console.warn("[DockerCard] open", e); }
852
852
  }}
853
853
  cloudTitle={dockerCloudTeam?.title}