cicy-desktop 2.1.205 → 2.1.207
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 +6 -6
- package/src/app-updater.js +27 -1
- package/src/backends/homepage-preload.js +3 -0
- package/src/backends/homepage-react/assets/index-D_1u1626.js +377 -0
- package/src/backends/homepage-react/index.html +1 -1
- package/src/backends/sidecar-ipc.js +62 -2
- package/src/i18n/locales/en.json +36 -2
- package/src/i18n/locales/fr.json +36 -2
- package/src/i18n/locales/ja.json +36 -2
- package/src/i18n/locales/zh-CN.json +36 -2
- package/src/sidecar/container-scripts/cicy-code-update.sh +104 -0
- package/src/sidecar/wsl-docker.js +215 -22
- package/workers/render/src/App.jsx +140 -9
- package/src/backends/homepage-react/assets/index-Bf9kuVZb.js +0 -377
|
@@ -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-D_1u1626.js"></script>
|
|
10
10
|
<link rel="stylesheet" crossorigin href="./assets/index-C6Zrdgc0.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
|
@@ -49,6 +49,26 @@ const APP_PORT = Number(process.env.CICY_DOCKER_APP_PORT || 8008);
|
|
|
49
49
|
// (含 port)区分。
|
|
50
50
|
const APP_CONTAINER = process.env.CICY_DOCKER_APP_CONTAINER || `cicy-code-docker-${APP_PORT}`;
|
|
51
51
|
const APP_VOLUME = process.env.CICY_DOCKER_APP_VOLUME || `cicy-team-${APP_PORT}`;
|
|
52
|
+
|
|
53
|
+
// 用户自定义的额外发布端口(除 :8008 外,给容器内 agent 服务从 Windows 直达用)。
|
|
54
|
+
// 持久化在 userData/docker-ports.json,bootstrap/recreate 都会带上 -p。lazy 取
|
|
55
|
+
// 路径(app 未 ready 时不取)。
|
|
56
|
+
function portsFile() { return path.join(require("electron").app.getPath("userData"), "docker-ports.json"); }
|
|
57
|
+
function sanitizePorts(arr) {
|
|
58
|
+
const out = [], seen = new Set([APP_PORT, 8008]);
|
|
59
|
+
for (const raw of Array.isArray(arr) ? arr : []) {
|
|
60
|
+
const p = Number(raw);
|
|
61
|
+
if (!Number.isInteger(p) || p < 1 || p > 65535 || seen.has(p)) continue;
|
|
62
|
+
seen.add(p); out.push(p);
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
function readExtraPorts() {
|
|
67
|
+
try { const j = JSON.parse(fs.readFileSync(portsFile(), "utf8")); return sanitizePorts(j && j.ports); } catch { return []; }
|
|
68
|
+
}
|
|
69
|
+
function writeExtraPorts(ports) {
|
|
70
|
+
try { fs.writeFileSync(portsFile(), JSON.stringify({ ports: sanitizePorts(ports) }, null, 2), "utf8"); } catch (e) { log.warn("[docker-ports] write failed:", e.message); }
|
|
71
|
+
}
|
|
52
72
|
const APP_MOUNT = process.env.CICY_DOCKER_APP_MOUNT || "/home/cicy";
|
|
53
73
|
// :8008 docker 的网关 endpoint。key 不再从 :8008 借(native 已退役)—— 容器只用它
|
|
54
74
|
// 自己独立云端 team 的 key(见 ensureDockerTeam / appOpts)。
|
|
@@ -115,7 +135,7 @@ function register({ sidecarLogPath } = {}) {
|
|
|
115
135
|
if (s.running) { try { ver = await require("../sidecar/version").running(APP_PORT); } catch {} }
|
|
116
136
|
// installed: distro 装了 OR :8008 健康(WSL 抽风查不到 distro 但容器在跑 → 也算装了,
|
|
117
137
|
// 否则卡片误显「下载安装」)。wslUnmanaged: 服务在跑但 WSL 管不到 → 卡片显式提示异常。
|
|
118
|
-
_dockerStatusCache = { installed: !!s.distro || !!s.healthy, dockerRunning: !!s.engineUp || !!s.healthy, running: !!s.running, unknown: !!s.unknown, wslUnmanaged: !!s.wslUnmanaged, version: ver, port: APP_PORT, platform: process.platform, chromeProxy: chromeProxyEnabled(), chromeProxyRunning: hostMihomo.running(), ts: Date.now() };
|
|
138
|
+
_dockerStatusCache = { installed: !!s.distro || !!s.healthy, dockerRunning: !!s.engineUp || !!s.healthy, running: !!s.running, unknown: !!s.unknown, wslUnmanaged: !!s.wslUnmanaged, wslWedged: !!s.wslWedged, version: ver, port: APP_PORT, platform: process.platform, chromeProxy: chromeProxyEnabled(), chromeProxyRunning: hostMihomo.running(), ts: Date.now() };
|
|
119
139
|
} catch (e) {
|
|
120
140
|
_dockerStatusCache = { installed: false, dockerRunning: false, running: false, unknown: true, port: APP_PORT, platform: process.platform, error: e.message, ts: Date.now() };
|
|
121
141
|
}
|
|
@@ -263,7 +283,7 @@ function register({ sidecarLogPath } = {}) {
|
|
|
263
283
|
await ensureDockerTeam().catch(() => {});
|
|
264
284
|
const env = { CICY_AI_GATEWAY_LLM_ENDPOINT: GATEWAY_ENDPOINT };
|
|
265
285
|
if (dockerTeamReg && dockerTeamReg.apiKey) env.CICY_AI_GATEWAY_LLM_API_KEY = dockerTeamReg.apiKey;
|
|
266
|
-
return { port: APP_PORT, container: APP_CONTAINER, volume: APP_VOLUME, env };
|
|
286
|
+
return { port: APP_PORT, container: APP_CONTAINER, volume: APP_VOLUME, env, extraPorts: readExtraPorts() };
|
|
267
287
|
};
|
|
268
288
|
// Register the running :8008 instance as a (custom) team so the card's "打开"
|
|
269
289
|
// reuses the token-injected open/reload flow. addTeam dedups by host:port.
|
|
@@ -383,6 +403,24 @@ function register({ sidecarLogPath } = {}) {
|
|
|
383
403
|
}
|
|
384
404
|
});
|
|
385
405
|
|
|
406
|
+
// 「修复 WSL」: WSL 卡死(wslWedged)时用户一键自救。先试重启 LxssManager;若还卡死(深度
|
|
407
|
+
// 死锁,杀不动)→ 返回 needsReboot,渲染层提示重启电脑(重启后启动 bootstrap 会自动重置坏
|
|
408
|
+
// distro + 重新导入)。服务恢复了就顺手跑一遍 bootstrap 自愈。
|
|
409
|
+
ipcMain.handle("docker:app-repair-wsl", async (e) => {
|
|
410
|
+
if (!APP_DOCKER_SUPPORTED) return { ok: false, error: "仅 Windows" };
|
|
411
|
+
const emit = (ev) => { try { e.sender.send("docker:app-progress", ev); } catch {} };
|
|
412
|
+
try {
|
|
413
|
+
const r = await appDocker.repairWsl({ emit });
|
|
414
|
+
if (r && r.ok) {
|
|
415
|
+
try { await ensureDockerTeam(); await appDocker.bootstrap({ ...(await appOpts()), onProgress: emit }); } catch (err) { log.warn(`[repair-wsl] bootstrap after repair: ${err.message}`); }
|
|
416
|
+
try { await registerAppTeam(); } catch {}
|
|
417
|
+
try { await maybeStartChromeProxy(); } catch {}
|
|
418
|
+
}
|
|
419
|
+
await refreshDockerStatus().catch(() => {});
|
|
420
|
+
return r;
|
|
421
|
+
} catch (err) { return { ok: false, error: err.message }; }
|
|
422
|
+
});
|
|
423
|
+
|
|
386
424
|
// ⋯ menu → 重启 cicy-code (supervisorctl restart cicy-code; daemons stay up).
|
|
387
425
|
ipcMain.handle("docker:app-restart", async () => {
|
|
388
426
|
try { const ok = await appDocker.restart({ container: APP_CONTAINER, port: APP_PORT, volume: APP_VOLUME }); return { ok: !!ok }; }
|
|
@@ -457,6 +495,28 @@ function register({ sidecarLogPath } = {}) {
|
|
|
457
495
|
}
|
|
458
496
|
});
|
|
459
497
|
|
|
498
|
+
// 端口设置:读当前已发布的额外端口(:8008 固定,不在列)。
|
|
499
|
+
ipcMain.handle("docker:get-ports", () => {
|
|
500
|
+
return { ok: true, mainPort: APP_PORT, ports: readExtraPorts() };
|
|
501
|
+
});
|
|
502
|
+
// 保存端口 → 持久化 → recreate 容器带上新的 -p(:8008 + 各额外端口)。volume 保留。
|
|
503
|
+
ipcMain.handle("docker:set-ports", async (e, input) => {
|
|
504
|
+
if (!APP_DOCKER_SUPPORTED) return { ok: false, error: "Docker cicy-code 仅支持 Windows" };
|
|
505
|
+
const ports = sanitizePorts(input && input.ports);
|
|
506
|
+
writeExtraPorts(ports);
|
|
507
|
+
try {
|
|
508
|
+
await ensureDockerTeam();
|
|
509
|
+
const result = await appDocker.recreate({
|
|
510
|
+
...(await appOpts()), // 已含 extraPorts: readExtraPorts()(刚写入的)
|
|
511
|
+
onProgress: (ev) => { try { e.sender.send("docker:app-progress", ev); } catch {} },
|
|
512
|
+
});
|
|
513
|
+
await registerAppTeam();
|
|
514
|
+
return { ok: true, ports, result };
|
|
515
|
+
} catch (err) {
|
|
516
|
+
return { ok: false, error: err.message };
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
|
|
460
520
|
// Start (or reuse) the cicy-code daemon. probeExisting inside start() reuses
|
|
461
521
|
// a healthy :8008; otherwise it spawns `npx cicy-code` / the Docker container.
|
|
462
522
|
ipcMain.handle("sidecar:start", async (e) => {
|
package/src/i18n/locales/en.json
CHANGED
|
@@ -213,7 +213,40 @@
|
|
|
213
213
|
"repairWsl": "Repair WSL",
|
|
214
214
|
"wslBrokenRepair": "WSL unmanaged · click Repair WSL to reinstall",
|
|
215
215
|
"openWslDir": "Open WSL folder",
|
|
216
|
-
"openProjectsDir": "Open projects folder"
|
|
216
|
+
"openProjectsDir": "Open projects folder",
|
|
217
|
+
"wslWedged": "WSL frozen · click Repair WSL",
|
|
218
|
+
"wslNeedReboot": "WSL service is stuck — please RESTART Windows; CiCy auto-repairs on next launch (old data is renamed/kept, not deleted).",
|
|
219
|
+
"wslRepaired": "WSL repaired",
|
|
220
|
+
"repairFailed": "Repair failed",
|
|
221
|
+
"updating": {
|
|
222
|
+
"checking": "Checking cicy-code version…",
|
|
223
|
+
"alreadyLatest": "Already up to date — v{{v}} ✅",
|
|
224
|
+
"toVersion": "Updating cicy-code → v{{v}}…",
|
|
225
|
+
"pulling": "Updating cicy-code (pulling latest)…",
|
|
226
|
+
"doneVersion": "cicy-code updated to v{{v}} 🎉",
|
|
227
|
+
"doneLatest": "cicy-code updated to latest 🎉",
|
|
228
|
+
"notReady": "Updated, but :8008 isn't responding yet — wait a moment or retry",
|
|
229
|
+
"failed": "Update failed: {{msg}} (this image may not support it; try Upgrade to reinstall)",
|
|
230
|
+
"hostResolveFail": "Host version lookup failed; resolving inside container…",
|
|
231
|
+
"scriptReady": "In-container update script refreshed (fast)",
|
|
232
|
+
"scriptPushFail": "Failed to push update script; using baked one",
|
|
233
|
+
"starting": "Starting cicy-code service…"
|
|
234
|
+
},
|
|
235
|
+
"ports": {
|
|
236
|
+
"menu": "Port settings",
|
|
237
|
+
"title": "Port settings",
|
|
238
|
+
"sub": "Extra ports (besides :8008) published so Windows can reach in-container services",
|
|
239
|
+
"mainFixed": ":8008 · cicy-code (fixed)",
|
|
240
|
+
"add": "+ Add port",
|
|
241
|
+
"ph": "Port 1-65535",
|
|
242
|
+
"save": "Save & rebuild",
|
|
243
|
+
"saving": "Saving…",
|
|
244
|
+
"cancel": "Cancel",
|
|
245
|
+
"hint": "Saving rebuilds the container (volume data kept) with a brief interruption",
|
|
246
|
+
"invalid": "Invalid port (1-65535, not 8008, no duplicates)",
|
|
247
|
+
"none": "No extra ports",
|
|
248
|
+
"remove": "Remove"
|
|
249
|
+
}
|
|
217
250
|
},
|
|
218
251
|
"common": {
|
|
219
252
|
"close": "Close",
|
|
@@ -466,7 +499,8 @@
|
|
|
466
499
|
"opening": "Opening {{url}} …",
|
|
467
500
|
"opened": "Opened",
|
|
468
501
|
"hintOpenFailed": "Got the token but failed to open the window: {{err}}",
|
|
469
|
-
"hintException": "Open failed with an exception: {{err}}"
|
|
502
|
+
"hintException": "Open failed with an exception: {{err}}",
|
|
503
|
+
"engineStartingNoReset": "Docker engine not running, starting it (without resetting WSL)…"
|
|
470
504
|
},
|
|
471
505
|
"dockerBadge": {
|
|
472
506
|
"install-docker": "Prep",
|
package/src/i18n/locales/fr.json
CHANGED
|
@@ -213,7 +213,40 @@
|
|
|
213
213
|
"repairWsl": "Réparer WSL",
|
|
214
214
|
"wslBrokenRepair": "WSL non géré · cliquez Réparer WSL pour réinstaller",
|
|
215
215
|
"openWslDir": "Ouvrir le dossier WSL",
|
|
216
|
-
"openProjectsDir": "Ouvrir le dossier projets"
|
|
216
|
+
"openProjectsDir": "Ouvrir le dossier projets",
|
|
217
|
+
"wslWedged": "WSL bloqué · cliquez Réparer WSL",
|
|
218
|
+
"wslNeedReboot": "Service WSL bloqué — REDÉMARREZ Windows ; réparation auto au prochain lancement (anciennes données renommées/conservées).",
|
|
219
|
+
"wslRepaired": "WSL réparé",
|
|
220
|
+
"repairFailed": "Échec de la réparation",
|
|
221
|
+
"updating": {
|
|
222
|
+
"checking": "Vérification de la version de cicy-code…",
|
|
223
|
+
"alreadyLatest": "Déjà à jour — v{{v}} ✅",
|
|
224
|
+
"toVersion": "Mise à jour de cicy-code → v{{v}}…",
|
|
225
|
+
"pulling": "Mise à jour de cicy-code (récupération de la dernière version)…",
|
|
226
|
+
"doneVersion": "cicy-code mis à jour vers v{{v}} 🎉",
|
|
227
|
+
"doneLatest": "cicy-code mis à jour vers la dernière version 🎉",
|
|
228
|
+
"notReady": "Mis à jour, mais :8008 ne répond pas encore — patientez ou réessayez",
|
|
229
|
+
"failed": "Échec de la mise à jour : {{msg}} (cette image peut ne pas le prendre en charge ; essayez « Mettre à niveau » pour réinstaller)",
|
|
230
|
+
"hostResolveFail": "Échec de la résolution de version côté hôte ; résolution dans le conteneur…",
|
|
231
|
+
"scriptReady": "Script de mise à jour du conteneur actualisé (rapide)",
|
|
232
|
+
"scriptPushFail": "Échec de l'envoi du script ; utilisation de la version intégrée",
|
|
233
|
+
"starting": "Démarrage du service cicy-code…"
|
|
234
|
+
},
|
|
235
|
+
"ports": {
|
|
236
|
+
"menu": "Réglage des ports",
|
|
237
|
+
"title": "Réglage des ports",
|
|
238
|
+
"sub": "Ports supplémentaires (hors :8008) publiés pour que Windows atteigne les services du conteneur",
|
|
239
|
+
"mainFixed": ":8008 · cicy-code (fixe)",
|
|
240
|
+
"add": "+ Ajouter un port",
|
|
241
|
+
"ph": "Port 1-65535",
|
|
242
|
+
"save": "Enregistrer et reconstruire",
|
|
243
|
+
"saving": "Enregistrement…",
|
|
244
|
+
"cancel": "Annuler",
|
|
245
|
+
"hint": "L'enregistrement reconstruit le conteneur (données du volume conservées), brève interruption",
|
|
246
|
+
"invalid": "Port invalide (1-65535, pas 8008, sans doublon)",
|
|
247
|
+
"none": "Aucun port supplémentaire",
|
|
248
|
+
"remove": "Retirer"
|
|
249
|
+
}
|
|
217
250
|
},
|
|
218
251
|
"common": {
|
|
219
252
|
"close": "Close",
|
|
@@ -466,7 +499,8 @@
|
|
|
466
499
|
"opening": "Ouverture de {{url}} …",
|
|
467
500
|
"opened": "Ouvert",
|
|
468
501
|
"hintOpenFailed": "Token obtenu mais échec d'ouverture de la fenêtre : {{err}}",
|
|
469
|
-
"hintException": "Exception lors de l'ouverture : {{err}}"
|
|
502
|
+
"hintException": "Exception lors de l'ouverture : {{err}}",
|
|
503
|
+
"engineStartingNoReset": "Moteur Docker non démarré, démarrage (sans réinitialiser WSL)…"
|
|
470
504
|
},
|
|
471
505
|
"dockerBadge": {
|
|
472
506
|
"install-docker": "Prép.",
|
package/src/i18n/locales/ja.json
CHANGED
|
@@ -213,7 +213,40 @@
|
|
|
213
213
|
"repairWsl": "WSL を修復",
|
|
214
214
|
"wslBrokenRepair": "WSL 管理異常 · 「WSL を修復」で再インストール",
|
|
215
215
|
"openWslDir": "WSL フォルダを開く",
|
|
216
|
-
"openProjectsDir": "プロジェクトフォルダを開く"
|
|
216
|
+
"openProjectsDir": "プロジェクトフォルダを開く",
|
|
217
|
+
"wslWedged": "WSL フリーズ · 「WSL を修復」をクリック",
|
|
218
|
+
"wslNeedReboot": "WSL サービスが停止不能です — Windows を再起動してください。次回起動時に自動修復します(旧データは改名保存、削除しません)。",
|
|
219
|
+
"wslRepaired": "WSL を修復しました",
|
|
220
|
+
"repairFailed": "修復に失敗",
|
|
221
|
+
"updating": {
|
|
222
|
+
"checking": "cicy-code のバージョンを確認中…",
|
|
223
|
+
"alreadyLatest": "すでに最新です — v{{v}} ✅",
|
|
224
|
+
"toVersion": "cicy-code を更新中 → v{{v}}…",
|
|
225
|
+
"pulling": "cicy-code を更新中(最新版を取得)…",
|
|
226
|
+
"doneVersion": "cicy-code を v{{v}} に更新しました 🎉",
|
|
227
|
+
"doneLatest": "cicy-code を最新版に更新しました 🎉",
|
|
228
|
+
"notReady": "更新しましたが :8008 がまだ応答しません — 少し待つか再試行してください",
|
|
229
|
+
"failed": "更新に失敗:{{msg}}(このイメージは未対応の可能性。「アップグレード」で再インストールを)",
|
|
230
|
+
"hostResolveFail": "ホストでのバージョン解決に失敗。コンテナ内で解決します…",
|
|
231
|
+
"scriptReady": "コンテナ内の更新スクリプトを更新(高速版)",
|
|
232
|
+
"scriptPushFail": "更新スクリプトの送信に失敗。内蔵版を使用します",
|
|
233
|
+
"starting": "cicy-code サービスを起動中…"
|
|
234
|
+
},
|
|
235
|
+
"ports": {
|
|
236
|
+
"menu": "ポート設定",
|
|
237
|
+
"title": "ポート設定",
|
|
238
|
+
"sub": ":8008 以外に公開し、Windows からコンテナ内サービスへ直接到達できるポート",
|
|
239
|
+
"mainFixed": ":8008 · cicy-code(固定)",
|
|
240
|
+
"add": "+ ポートを追加",
|
|
241
|
+
"ph": "ポート 1-65535",
|
|
242
|
+
"save": "保存して再構築",
|
|
243
|
+
"saving": "保存中…",
|
|
244
|
+
"cancel": "キャンセル",
|
|
245
|
+
"hint": "保存するとコンテナを再構築します(ボリュームのデータは保持、短時間中断)",
|
|
246
|
+
"invalid": "無効なポート(1-65535、8008 不可、重複不可)",
|
|
247
|
+
"none": "追加ポートなし",
|
|
248
|
+
"remove": "削除"
|
|
249
|
+
}
|
|
217
250
|
},
|
|
218
251
|
"common": {
|
|
219
252
|
"close": "Close",
|
|
@@ -466,7 +499,8 @@
|
|
|
466
499
|
"opening": "{{url}} を開いています…",
|
|
467
500
|
"opened": "開きました",
|
|
468
501
|
"hintOpenFailed": "token は取得しましたがウィンドウを開けませんでした:{{err}}",
|
|
469
|
-
"hintException": "オープン中に例外:{{err}}"
|
|
502
|
+
"hintException": "オープン中に例外:{{err}}",
|
|
503
|
+
"engineStartingNoReset": "Docker エンジン未起動、起動します(WSL はリセットしません)…"
|
|
470
504
|
},
|
|
471
505
|
"dockerBadge": {
|
|
472
506
|
"install-docker": "準備",
|
|
@@ -213,7 +213,40 @@
|
|
|
213
213
|
"repairWsl": "修复 WSL",
|
|
214
214
|
"wslBrokenRepair": "WSL 管理异常 · 点「修复 WSL」重装",
|
|
215
215
|
"openWslDir": "打开 WSL 目录",
|
|
216
|
-
"openProjectsDir": "打开项目目录"
|
|
216
|
+
"openProjectsDir": "打开项目目录",
|
|
217
|
+
"wslWedged": "WSL 卡死 · 点「修复 WSL」",
|
|
218
|
+
"wslNeedReboot": "WSL 服务卡死,请【重启 Windows】;重启后打开 CiCy 会自动修复(旧数据已改名备份,不删)。",
|
|
219
|
+
"wslRepaired": "WSL 已修复",
|
|
220
|
+
"repairFailed": "修复失败",
|
|
221
|
+
"updating": {
|
|
222
|
+
"checking": "检查 cicy-code 版本…",
|
|
223
|
+
"alreadyLatest": "已是最新版 v{{v}} ✅",
|
|
224
|
+
"toVersion": "更新 cicy-code → v{{v}}…",
|
|
225
|
+
"pulling": "更新 cicy-code(拉取最新版)…",
|
|
226
|
+
"doneVersion": "cicy-code 已更新到 v{{v}} 🎉",
|
|
227
|
+
"doneLatest": "cicy-code 已更新到最新 🎉",
|
|
228
|
+
"notReady": "更新了但 :8008 还没响应——稍等或点重试",
|
|
229
|
+
"failed": "更新失败:{{msg}}(此镜像可能不支持,试试「升级」重装)",
|
|
230
|
+
"hostResolveFail": "宿主机解析版本失败,改由容器内解析…",
|
|
231
|
+
"scriptReady": "已更新容器内更新脚本(快速版)",
|
|
232
|
+
"scriptPushFail": "推送更新脚本失败,改用镜像内置脚本",
|
|
233
|
+
"starting": "启动 cicy-code 服务…"
|
|
234
|
+
},
|
|
235
|
+
"ports": {
|
|
236
|
+
"menu": "端口设置",
|
|
237
|
+
"title": "端口设置",
|
|
238
|
+
"sub": "除 :8008 外,额外发布、可从 Windows 直达容器内服务的端口",
|
|
239
|
+
"mainFixed": ":8008 · cicy-code(固定)",
|
|
240
|
+
"add": "+ 添加端口",
|
|
241
|
+
"ph": "端口号 1-65535",
|
|
242
|
+
"save": "保存并重建",
|
|
243
|
+
"saving": "保存中…",
|
|
244
|
+
"cancel": "取消",
|
|
245
|
+
"hint": "保存会重建容器(volume 数据保留),会有短暂中断",
|
|
246
|
+
"invalid": "有端口无效(1-65535,不能是 8008,不能重复)",
|
|
247
|
+
"none": "暂无额外端口",
|
|
248
|
+
"remove": "移除"
|
|
249
|
+
}
|
|
217
250
|
},
|
|
218
251
|
"common": {
|
|
219
252
|
"close": "关闭",
|
|
@@ -466,7 +499,8 @@
|
|
|
466
499
|
"opening": "打开 {{url}} …",
|
|
467
500
|
"opened": "已打开",
|
|
468
501
|
"hintOpenFailed": "拿到 token 但打开窗口失败:{{err}}",
|
|
469
|
-
"hintException": "打开过程异常:{{err}}"
|
|
502
|
+
"hintException": "打开过程异常:{{err}}",
|
|
503
|
+
"engineStartingNoReset": "Docker 引擎未运行,正在启动(不重置 WSL)…"
|
|
470
504
|
},
|
|
471
505
|
"dockerBadge": {
|
|
472
506
|
"install-docker": "准备",
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Vendored copy pushed INTO the running container by cicy-desktop at update time
|
|
3
|
+
# (see wsl-docker.js update()), then executed. This is the authoritative script
|
|
4
|
+
# for the "更新 cicy-code" flow: shipping a fix here rides cicy-desktop's own
|
|
5
|
+
# auto-update (OSS, reaches Windows) — NO new container image / pull required,
|
|
6
|
+
# which is why we cp-then-run instead of relying on the baked image copy.
|
|
7
|
+
#
|
|
8
|
+
# Hot-update cicy-code WITHOUT bouncing the container, the cloudflared tunnel,
|
|
9
|
+
# or any user daemons: install the new version side-by-side, repoint one symlink,
|
|
10
|
+
# restart only the supervisor program.
|
|
11
|
+
#
|
|
12
|
+
# cicy-code-update # → latest
|
|
13
|
+
# cicy-code-update 2.3.16 # → a pinned version
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
|
|
16
|
+
HOME_DIR="${HOME:-/home/cicy}"
|
|
17
|
+
|
|
18
|
+
# Registry selection: honor an explicit NPM_REGISTRY (cicy-desktop injects it via
|
|
19
|
+
# `docker exec -e` per host network) — otherwise probe registry.npmjs.org with a
|
|
20
|
+
# short timeout: reachable fast → official npm (best overseas); slow/blocked →
|
|
21
|
+
# registry.npmmirror.com (CN mirror, the safe default).
|
|
22
|
+
NPM_OFFICIAL="https://registry.npmjs.org"
|
|
23
|
+
NPM_CN="https://registry.npmmirror.com"
|
|
24
|
+
pick_registry() {
|
|
25
|
+
if [ -n "${NPM_REGISTRY:-}" ]; then echo "$NPM_REGISTRY"; return; fi
|
|
26
|
+
if curl -fsS -m 3 --connect-timeout 3 -o /dev/null "$NPM_OFFICIAL/cicy-code"; then
|
|
27
|
+
echo "$NPM_OFFICIAL"
|
|
28
|
+
else
|
|
29
|
+
echo "$NPM_CN"
|
|
30
|
+
fi
|
|
31
|
+
}
|
|
32
|
+
REG="$(pick_registry)"
|
|
33
|
+
RT="$HOME_DIR/cicy-ai/runtime/cicy-code"
|
|
34
|
+
LINK="$HOME_DIR/.local/bin/cicy-code"
|
|
35
|
+
VERSIONS="$HOME_DIR/cicy-ai/runtime/versions.json"
|
|
36
|
+
SVCTL="supervisorctl -c /etc/supervisor/supervisord.conf"
|
|
37
|
+
|
|
38
|
+
want="${1:-latest}"
|
|
39
|
+
log() { printf '[cicy-code-update] %s\n' "$*"; }
|
|
40
|
+
log "registry: $REG"
|
|
41
|
+
|
|
42
|
+
# Resolve the concrete version number (so the install dir is version-named and
|
|
43
|
+
# re-runs are idempotent / cacheable).
|
|
44
|
+
if printf '%s' "$want" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+'; then
|
|
45
|
+
# Caller (cicy-desktop) already resolved a concrete version on the HOST (fast,
|
|
46
|
+
# reliable network) → trust it, skip the in-container `npm view` entirely. This
|
|
47
|
+
# is the path that avoids the ~2min npm-view hang on a slow container registry.
|
|
48
|
+
ver="$want"
|
|
49
|
+
else
|
|
50
|
+
# 'latest' / range → resolve via registry. FAIL FAST: npm's default retry/backoff
|
|
51
|
+
# can burn ~2min on a slow/blocked registry — cap retries+timeout so one bad
|
|
52
|
+
# registry fails in ~15s, then fall back to the other registry instead of hanging.
|
|
53
|
+
resolve_ver() {
|
|
54
|
+
npm view "cicy-code@${want}" version --registry "$1" \
|
|
55
|
+
--fetch-retries=1 --fetch-timeout=15000 --fetch-retry-mintimeout=3000 --fetch-retry-maxtimeout=15000 \
|
|
56
|
+
2>/dev/null | tail -n1
|
|
57
|
+
}
|
|
58
|
+
ver="$(resolve_ver "$REG")"
|
|
59
|
+
if [ -z "$ver" ]; then
|
|
60
|
+
alt="$NPM_CN"; [ "$REG" = "$NPM_CN" ] && alt="$NPM_OFFICIAL"
|
|
61
|
+
log "registry $REG slow/unreachable → falling back to $alt"
|
|
62
|
+
ver="$(resolve_ver "$alt")"
|
|
63
|
+
[ -n "$ver" ] && REG="$alt"
|
|
64
|
+
fi
|
|
65
|
+
fi
|
|
66
|
+
[ -n "$ver" ] || { log "could not resolve cicy-code@${want}"; exit 1; }
|
|
67
|
+
dest="$RT/$ver"
|
|
68
|
+
|
|
69
|
+
if [ -x "$dest/bin/cicy-code" ]; then
|
|
70
|
+
log "v$ver already installed → repointing"
|
|
71
|
+
else
|
|
72
|
+
log "installing v$ver from $REG"
|
|
73
|
+
rm -rf "$dest"
|
|
74
|
+
mkdir -p "$dest"
|
|
75
|
+
npm install -g "cicy-code@$ver" --prefix "$dest" --registry "$REG" \
|
|
76
|
+
--fetch-retries=2 --fetch-timeout=60000 --fetch-retry-maxtimeout=30000
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
mkdir -p "$(dirname "$LINK")"
|
|
80
|
+
ln -sfn "$dest/bin/cicy-code" "$LINK"
|
|
81
|
+
# Keep the npm-global bin (first on PATH) following the canonical link too, so
|
|
82
|
+
# interactive `cicy-code` matches what supervisor runs.
|
|
83
|
+
ln -sfn "$LINK" "$HOME_DIR/.npm-global/bin/cicy-code" 2>/dev/null || true
|
|
84
|
+
|
|
85
|
+
# Record current pointer (merge into the shared versions.json).
|
|
86
|
+
mkdir -p "$(dirname "$VERSIONS")"
|
|
87
|
+
tmp="$(mktemp)"
|
|
88
|
+
if [ -s "$VERSIONS" ] && jq -e . "$VERSIONS" >/dev/null 2>&1; then
|
|
89
|
+
jq --arg v "$ver" '.["cicy-code"] = ((.["cicy-code"] // {}) + {current: $v})' "$VERSIONS" > "$tmp"
|
|
90
|
+
else
|
|
91
|
+
jq -n --arg v "$ver" '{"cicy-code": {current: $v}}' > "$tmp"
|
|
92
|
+
fi
|
|
93
|
+
mv "$tmp" "$VERSIONS"
|
|
94
|
+
|
|
95
|
+
log "symlink → $(readlink -f "$LINK")"
|
|
96
|
+
|
|
97
|
+
# Reload: restart only this program (no-op gracefully if supervisord isn't up).
|
|
98
|
+
if $SVCTL pid >/dev/null 2>&1; then
|
|
99
|
+
log "restarting via supervisor"
|
|
100
|
+
$SVCTL restart cicy-code
|
|
101
|
+
else
|
|
102
|
+
log "supervisord not running yet; symlink set, will start on boot"
|
|
103
|
+
fi
|
|
104
|
+
log "done → v$ver"
|