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.
- package/package.json +1 -1
- package/src/backends/homepage-react/assets/{index-C8HjxypR.js → index-DczjleYe.js} +7 -7
- package/src/backends/homepage-react/index.html +1 -1
- package/src/backends/sidecar-ipc.js +28 -30
- package/src/i18n/locales/en.json +2 -1
- package/src/i18n/locales/fr.json +2 -1
- package/src/i18n/locales/ja.json +2 -1
- package/src/i18n/locales/zh-CN.json +2 -1
- package/src/main.js +15 -0
- package/workers/render/src/App.jsx +1 -1
|
@@ -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-
|
|
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
|
-
//
|
|
50
|
-
//
|
|
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; // 未登录 →
|
|
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
|
-
//
|
|
239
|
-
//
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
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 (
|
|
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();
|
package/src/i18n/locales/en.json
CHANGED
|
@@ -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",
|
package/src/i18n/locales/fr.json
CHANGED
|
@@ -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",
|
package/src/i18n/locales/ja.json
CHANGED
|
@@ -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": "閉じる",
|
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)
|
|
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}
|