From b2ca7cdd4d25cc223e8f0168fe0c2ecff6602132 Mon Sep 17 00:00:00 2001 From: Hermes Team Date: Mon, 31 Aug 2026 21:46:30 +0700 Subject: [PATCH] =?UTF-8?q?fix:=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=B2=20=D0=B8=D0=BD=D1=82=D0=B5=D1=80=D1=84=D0=B5=D0=B9=D1=81?= =?UTF-8?q?=D0=B5=20=D0=B1=D1=8B=D0=BB=D0=B0=20=D0=B7=D0=B0=D1=88=D0=B8?= =?UTF-8?q?=D1=82=D0=B0=20=D0=B2=20=D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=82?= =?UTF-8?q?=D0=BA=D0=B5;=20=D1=83=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=BF=D0=B0=D0=B4=D0=B0=D0=BB=D0=B0=20=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=B7=D0=B0=D0=BD=D1=8F=D1=82=D0=BE=D0=BC=20=D1=84?= =?UTF-8?q?=D0=B0=D0=B9=D0=BB=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Версия. В index.html номер стоял руками в двух местах, а в app.js был запасным значением '0.1.1'. Номер сборки приходил из API и обновлялся, версия — нет: владелец обновился до e6eab12 и увидел v0.1.1. Подъём версии в пяти местах бэкенда до экрана не доходил вовсе. Теперь версия берётся только из API; если сервер её не передал, пишется Н/Д с причиной, а не правдоподобный номер. Установка. Отказ остановки прежнего хаба прерывал установку целиком, и владелец получал голый код 15. Теперь неудачная остановка не отменяет установку: причина показывается, работа продолжается, и если файл действительно занят, об этом скажет копирование с именем файла. Копирование файлов получило повтор: процесс мог не успеть отпустить файл после остановки. Пять попыток с паузой вместо отказа с первой. 599 passed, ruff clean. Co-Authored-By: Claude Opus 5 --- installer/HermesHubSetup.cs | 40 +++++++++++++++---- .../router/web/static/app.js | 13 +++++- .../router/web/static/index.html | 4 +- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/installer/HermesHubSetup.cs b/installer/HermesHubSetup.cs index b050a1a..4d8328b 100644 --- a/installer/HermesHubSetup.cs +++ b/installer/HermesHubSetup.cs @@ -264,6 +264,19 @@ namespace HermesHubSetup } // Restrict cleanup to this installation. Never kill arbitrary Python/browser processes. + public static string StopWarning = ""; + + // Процесс мог не успеть отпустить файл. Один отказ по занятости — не приговор. + static void CopyWithRetry(string source, string destination) + { + for (int attempt = 1; ; attempt++) + { + try { File.Copy(source, destination, true); return; } + catch (IOException) { if (attempt >= 5) throw; System.Threading.Thread.Sleep(700); } + catch (UnauthorizedAccessException) { if (attempt >= 5) throw; System.Threading.Thread.Sleep(700); } + } + } + public static void StopOwnedRuntime(string home, bool includeLauncher) { string escaped = Path.GetFullPath(home).TrimEnd('\\').Replace("'", "''"); @@ -296,7 +309,18 @@ namespace HermesHubSetup try { - StopOwnedRuntime(HermesHome, true); + // Неудачная остановка прежнего хаба не повод отменять установку. + // Раньше любой ненулевой выход скрипта останавливал всё, и владелец + // видел голый код 15. Если процесс уцелел, копирование само скажет, + // какой файл занят. + try { StopOwnedRuntime(HermesHome, true); } + catch (Exception stopEx) + { + StopWarning = stopEx.Message; + if (progressCallback != null) + progressCallback("Не удалось остановить прежний Hermes Hub: " + stopEx.Message + + ". Продолжаю установку.", 5); + } if (progressCallback != null) progressCallback("Preparing installation directory...", 10); if (!Directory.Exists(TargetInstallDir)) { @@ -313,8 +337,8 @@ namespace HermesHubSetup if (File.Exists(launcherSrc)) { - File.Copy(launcherSrc, Path.Combine(TargetInstallDir, "HermesHub.exe"), true); - File.Copy(launcherSrc, Path.Combine(HermesHome, "HermesHub.exe"), true); + CopyWithRetry(launcherSrc, Path.Combine(TargetInstallDir, "HermesHub.exe")); + CopyWithRetry(launcherSrc, Path.Combine(HermesHome, "HermesHub.exe")); } string webLauncherSrc = Path.Combine(sourceRoot, @"launcher\HermesHubWeb.exe"); @@ -325,15 +349,15 @@ namespace HermesHubSetup if (File.Exists(webLauncherSrc)) { - File.Copy(webLauncherSrc, Path.Combine(TargetInstallDir, "HermesHubWeb.exe"), true); - File.Copy(webLauncherSrc, Path.Combine(HermesHome, "HermesHubWeb.exe"), true); + CopyWithRetry(webLauncherSrc, Path.Combine(TargetInstallDir, "HermesHubWeb.exe")); + CopyWithRetry(webLauncherSrc, Path.Combine(HermesHome, "HermesHubWeb.exe")); } // Copy Setup.exe itself to target dir for uninstaller/repair string setupSrc = Process.GetCurrentProcess().MainModule.FileName; if (File.Exists(setupSrc)) { - try { File.Copy(setupSrc, Path.Combine(TargetInstallDir, "HermesHubSetup.exe"), true); } catch { } + try { CopyWithRetry(setupSrc, Path.Combine(TargetInstallDir, "HermesHubSetup.exe")); } catch { } } // 2. Install UI & System Dependencies into Hermes Python Environment @@ -392,7 +416,7 @@ namespace HermesHubSetup string templateConfig = Path.Combine(sourceRoot, @"config\router_profiles.example.yaml"); if (!File.Exists(runtimeConfig) && File.Exists(templateConfig)) { - File.Copy(templateConfig, runtimeConfig, true); + CopyWithRetry(templateConfig, runtimeConfig); } // 6. Create Start Menu Shortcut @@ -529,7 +553,7 @@ namespace HermesHubSetup string fileName = Path.GetFileName(file); srcFiles.Add(fileName); string destFile = Path.Combine(dst, fileName); - File.Copy(file, destFile, true); + CopyWithRetry(file, destFile); } // Remove destination files that do not exist in source or are .pyc diff --git a/src/antigravity_provider/router/web/static/app.js b/src/antigravity_provider/router/web/static/app.js index cdc2bcf..85ef806 100644 --- a/src/antigravity_provider/router/web/static/app.js +++ b/src/antigravity_provider/router/web/static/app.js @@ -2293,10 +2293,19 @@ function renderUpdateUI() { const releaseMeta = document.getElementById('update-release-meta'); const releaseNotes = document.getElementById('update-release-notes'); - const curVer = (latestUpdateInfo && latestUpdateInfo.current_version) || (currentSettings && currentSettings.version) || '0.1.1'; + // Версия берётся ТОЛЬКО из API. Раньше номер был зашит в разметке и в + // запасном значении: подъём версии в коде до интерфейса не доходил, и + // владелец видел старый номер при новой сборке. + const curVer = (latestUpdateInfo && latestUpdateInfo.current_version) || (currentSettings && currentSettings.version) || ''; const cDisplay = installedCommit ? installedCommit.slice(0, 7) : 'неизвестно'; if (updateInfoDesc) { - updateInfoDesc.textContent = `Hermes Hub v${curVer} (сборка: ${cDisplay})`; + updateInfoDesc.textContent = curVer + ? `Hermes Hub v${curVer} (сборка: ${cDisplay})` + : `Hermes Hub (сборка: ${cDisplay}) — Н/Д: версия не передана сервером`; + } + const versionTag = document.getElementById('version-tag'); + if (versionTag) { + versionTag.textContent = curVer ? `Hermes Hub Web v${curVer}` : 'Hermes Hub Web — Н/Д: версия не передана сервером'; } if (statusBadge) { diff --git a/src/antigravity_provider/router/web/static/index.html b/src/antigravity_provider/router/web/static/index.html index 487ddf0..885b7f8 100644 --- a/src/antigravity_provider/router/web/static/index.html +++ b/src/antigravity_provider/router/web/static/index.html @@ -66,7 +66,7 @@ Загрузка данных... -
Hermes Hub Web v0.1.1
+
Hermes Hub Web
@@ -600,7 +600,7 @@
Текущая версия и сборка
-
Hermes Hub v0.1.1
+
Hermes Hub
Не проверено