feat: one-click agent upgrade from hosts list (0.3.9)

Add Omada-style git version arrow in the agent version column to trigger WinRM/SSH background updates, and soften host detail live refresh with debounced incremental event patches.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-24 15:32:09 +10:00
parent 0601aafd2d
commit 9053ef0588
7 changed files with 352 additions and 38 deletions
+27 -17
View File
@@ -67,13 +67,14 @@
<td>{{ h.id }}</td>
<td>{{ h.display_name || h.hostname }}</td>
<td>{{ h.hostname }}</td>
<td>
<span
:class="{ 'agent-version-outdated': isVersionOutdated(h) }"
:title="versionTitle(h)"
>
{{ h.product_version || "—" }}
</span>
<td @click.stop>
<HostAgentVersionUpgrade
:host="h"
:git="data"
:updating="upgradingHostId === h.id"
:outdated-highlight="isVersionOutdated(h)"
@upgrade="startAgentUpgrade(h)"
/>
</td>
<td>{{ h.os_family }}</td>
<td>{{ h.ipv4 || "—" }}</td>
@@ -125,6 +126,13 @@ import {
import { bumpLatestAgentVersion, patchHostSummaryFromDetail } from "../utils/hostsLiveUpdate";
import { subscribeHostPatch } from "../utils/hostPatchBus";
import { isAgentVersionOutdated } from "../utils/agentVersion";
import {
isGitAgentUpgradeAvailable,
remoteActionKindForHost,
remoteActionTitleForHost,
} from "../utils/hostAgentUpgrade";
import { runHostRemoteAction } from "../composables/useHostRemoteAction";
import HostAgentVersionUpgrade from "../components/HostAgentVersionUpgrade.vue";
const router = useRouter();
const route = useRoute();
@@ -188,6 +196,7 @@ const initialSort = loadHostsSortPrefs();
const sortBy = ref<SortKey>(initialSort.sortBy);
const sortDir = ref<"asc" | "desc">(initialSort.sortDir);
const deletingId = ref<number | null>(null);
const upgradingHostId = ref<number | null>(null);
let patchingHostRow = false;
let unsubscribeHostPatch: (() => void) | null = null;
@@ -223,17 +232,18 @@ function isVersionOutdated(h: HostSummary): boolean {
return isAgentVersionOutdated(h.product_version, reference);
}
function versionTitle(h: HostSummary): string {
const reference =
data.value?.reference_agent_versions?.[h.product] ??
data.value?.latest_agent_versions?.[h.product];
if (!isVersionOutdated(h)) return "";
if (!reference) return "Устаревшая версия агента";
const fromSettings = data.value?.reference_agent_versions?.[h.product];
if (fromSettings && fromSettings !== data.value?.latest_agent_versions?.[h.product]) {
return `Устарела относительно эталона ${reference} (настройки SAC)`;
async function startAgentUpgrade(h: HostSummary) {
if (!isGitAgentUpgradeAvailable(h, data.value) || upgradingHostId.value != null) {
return;
}
const kind = remoteActionKindForHost(h);
if (!kind) return;
upgradingHostId.value = h.id;
try {
await runHostRemoteAction(h.id, remoteActionTitleForHost(h), kind);
} finally {
upgradingHostId.value = null;
}
return `Устарела относительно эталона ${reference}`;
}
function openHost(id: number) {