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:
@@ -53,3 +53,14 @@ export function isAgentVersionNewer(
|
||||
if (!prev) return true;
|
||||
return compareVersions(next, prev) > 0;
|
||||
}
|
||||
|
||||
/** Хост строго младше целевой версии (например из git), без порога lag. */
|
||||
export function isAgentVersionBehind(
|
||||
hostVersion: string | null | undefined,
|
||||
targetVersion: string | null | undefined,
|
||||
): boolean {
|
||||
const host = parseAgentVersion(hostVersion);
|
||||
const target = parseAgentVersion(targetVersion);
|
||||
if (!host || !target) return false;
|
||||
return compareVersions(host, target) < 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import type { HostSummary } from "../api";
|
||||
import type { HostRemoteActionKind } from "../composables/useHostRemoteAction";
|
||||
import { isAgentVersionBehind } from "./agentVersion";
|
||||
|
||||
export const PRODUCT_RDP = "rdp-login-monitor";
|
||||
export const PRODUCT_SSH = "ssh-monitor";
|
||||
|
||||
export interface AgentGitVersions {
|
||||
git_latest_rdp_version?: string | null;
|
||||
git_latest_ssh_version?: string | null;
|
||||
}
|
||||
|
||||
export function isWindowsAgentHost(host: Pick<HostSummary, "os_family" | "product">): boolean {
|
||||
if ((host.os_family || "").toLowerCase() === "windows") return true;
|
||||
return host.product === PRODUCT_RDP;
|
||||
}
|
||||
|
||||
export function isLinuxAgentHost(host: Pick<HostSummary, "os_family" | "product">): boolean {
|
||||
if ((host.os_family || "").toLowerCase() === "linux") return true;
|
||||
return host.product === PRODUCT_SSH;
|
||||
}
|
||||
|
||||
export function gitTargetVersionForHost(
|
||||
host: Pick<HostSummary, "os_family" | "product">,
|
||||
git: AgentGitVersions | null | undefined,
|
||||
): string | null {
|
||||
if (!git) return null;
|
||||
if (isWindowsAgentHost(host)) {
|
||||
return git.git_latest_rdp_version?.trim() || null;
|
||||
}
|
||||
if (isLinuxAgentHost(host)) {
|
||||
return git.git_latest_ssh_version?.trim() || null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function isGitAgentUpgradeAvailable(
|
||||
host: Pick<HostSummary, "os_family" | "product" | "product_version">,
|
||||
git: AgentGitVersions | null | undefined,
|
||||
): boolean {
|
||||
const target = gitTargetVersionForHost(host, git);
|
||||
if (!target || !host.product_version?.trim()) return false;
|
||||
return isAgentVersionBehind(host.product_version, target);
|
||||
}
|
||||
|
||||
export function remoteActionKindForHost(
|
||||
host: Pick<HostSummary, "os_family" | "product">,
|
||||
): HostRemoteActionKind | null {
|
||||
if (isWindowsAgentHost(host)) return "fallback";
|
||||
if (isLinuxAgentHost(host)) return "ssh-update";
|
||||
return null;
|
||||
}
|
||||
|
||||
export function remoteActionTitleForHost(host: HostSummary): string {
|
||||
const label = host.display_name || host.hostname;
|
||||
if (isWindowsAgentHost(host)) {
|
||||
return `Обновление ${label} через WinRM`;
|
||||
}
|
||||
return `Обновление ssh-monitor (SSH): ${label}`;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import type { EventListResponse, EventSummary, HostDetail } from "../api";
|
||||
import { isAgentVersionBehind } from "./agentVersion";
|
||||
import type { AgentGitVersions } from "./hostAgentUpgrade";
|
||||
import { gitTargetVersionForHost } from "./hostAgentUpgrade";
|
||||
|
||||
/** Точечное обновление карточки хоста по событию ingest (без полного GET /hosts/{id}). */
|
||||
export function patchHostDetailFromEvent(host: HostDetail, ev: EventSummary): void {
|
||||
host.last_seen_at = ev.received_at || ev.occurred_at;
|
||||
host.event_count = (host.event_count ?? 0) + 1;
|
||||
if (ev.product_version?.trim()) {
|
||||
host.product_version = ev.product_version.trim();
|
||||
}
|
||||
}
|
||||
|
||||
export function recalcVersionStatusFromGit(
|
||||
host: HostDetail,
|
||||
git: AgentGitVersions | null | undefined,
|
||||
): void {
|
||||
const target = gitTargetVersionForHost(host, git);
|
||||
if (!host.product_version?.trim() || !target) {
|
||||
return;
|
||||
}
|
||||
host.version_status = isAgentVersionBehind(host.product_version, target) ? "outdated" : "ok";
|
||||
}
|
||||
|
||||
/** Добавляет событие в начало списка на стр. 1, если его ещё нет. */
|
||||
export function prependHostEventIfMissing(
|
||||
events: EventListResponse | null,
|
||||
ev: EventSummary,
|
||||
page: number,
|
||||
): boolean {
|
||||
if (!events || page !== 1) return false;
|
||||
if (events.items.some((row) => row.id === ev.id)) return false;
|
||||
events.items = [ev, ...events.items];
|
||||
events.total = (events.total ?? 0) + 1;
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user