Integrate plugin with local monitor bridge

This commit is contained in:
zhi
2026-03-21 16:07:01 +00:00
parent 9f649e2b39
commit 78a61e0fb2
12 changed files with 225 additions and 5 deletions

View File

@@ -3,6 +3,7 @@ export interface HarborForgeMonitorConfig {
backendUrl?: string;
identifier?: string;
apiKey?: string;
monitorPort?: number;
reportIntervalSec?: number;
httpFallbackIntervalSec?: number;
logLevel?: 'debug' | 'info' | 'warn' | 'error';

View File

@@ -1 +1 @@
{"version":3,"file":"live-config.d.ts","sourceRoot":"","sources":["live-config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;CAChD;AAED,UAAU,qBAAqB;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,qBAAqB,EAC1B,QAAQ,EAAE,wBAAwB,GACjC,wBAAwB,CAqB1B"}
{"version":3,"file":"live-config.d.ts","sourceRoot":"","sources":["live-config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;CAChD;AAED,UAAU,qBAAqB;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,qBAAqB,EAC1B,QAAQ,EAAE,wBAAwB,GACjC,wBAAwB,CAqB1B"}

View File

@@ -5,7 +5,7 @@ function getLivePluginConfig(api, fallback) {
const root = api.config || {};
const plugins = root.plugins || {};
const entries = plugins.entries || {};
const entry = entries['harborforge-monitor'] || {};
const entry = entries['harbor-forge'] || {};
const cfg = entry.config || {};
if (Object.keys(cfg).length > 0 || Object.keys(entry).length > 0) {
return {

View File

@@ -1 +1 @@
{"version":3,"file":"live-config.js","sourceRoot":"","sources":["live-config.ts"],"names":[],"mappings":";;AAcA,kDAwBC;AAxBD,SAAgB,mBAAmB,CACjC,GAA0B,EAC1B,QAAkC;IAElC,MAAM,IAAI,GAAI,GAAG,CAAC,MAAkC,IAAI,EAAE,CAAC;IAC3D,MAAM,OAAO,GAAI,IAAI,CAAC,OAAmC,IAAI,EAAE,CAAC;IAChE,MAAM,OAAO,GAAI,OAAO,CAAC,OAAmC,IAAI,EAAE,CAAC;IACnE,MAAM,KAAK,GAAI,OAAO,CAAC,qBAAqB,CAA6B,IAAI,EAAE,CAAC;IAChF,MAAM,GAAG,GAAI,KAAK,CAAC,MAAkC,IAAI,EAAE,CAAC;IAE5D,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjE,OAAO;YACL,GAAG,QAAQ;YACX,GAAG,GAAG;YACN,OAAO,EACL,OAAO,GAAG,CAAC,OAAO,KAAK,SAAS;gBAC9B,CAAC,CAAC,GAAG,CAAC,OAAO;gBACb,CAAC,CAAC,OAAO,KAAK,CAAC,OAAO,KAAK,SAAS;oBAClC,CAAC,CAAC,KAAK,CAAC,OAAO;oBACf,CAAC,CAAC,QAAQ,CAAC,OAAO;SACG,CAAC;IAChC,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
{"version":3,"file":"live-config.js","sourceRoot":"","sources":["live-config.ts"],"names":[],"mappings":";;AAeA,kDAwBC;AAxBD,SAAgB,mBAAmB,CACjC,GAA0B,EAC1B,QAAkC;IAElC,MAAM,IAAI,GAAI,GAAG,CAAC,MAAkC,IAAI,EAAE,CAAC;IAC3D,MAAM,OAAO,GAAI,IAAI,CAAC,OAAmC,IAAI,EAAE,CAAC;IAChE,MAAM,OAAO,GAAI,OAAO,CAAC,OAAmC,IAAI,EAAE,CAAC;IACnE,MAAM,KAAK,GAAI,OAAO,CAAC,cAAc,CAA6B,IAAI,EAAE,CAAC;IACzE,MAAM,GAAG,GAAI,KAAK,CAAC,MAAkC,IAAI,EAAE,CAAC;IAE5D,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjE,OAAO;YACL,GAAG,QAAQ;YACX,GAAG,GAAG;YACN,OAAO,EACL,OAAO,GAAG,CAAC,OAAO,KAAK,SAAS;gBAC9B,CAAC,CAAC,GAAG,CAAC,OAAO;gBACb,CAAC,CAAC,OAAO,KAAK,CAAC,OAAO,KAAK,SAAS;oBAClC,CAAC,CAAC,KAAK,CAAC,OAAO;oBACf,CAAC,CAAC,QAAQ,CAAC,OAAO;SACG,CAAC;IAChC,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}

View File

@@ -3,6 +3,7 @@ export interface HarborForgeMonitorConfig {
backendUrl?: string;
identifier?: string;
apiKey?: string;
monitorPort?: number;
reportIntervalSec?: number;
httpFallbackIntervalSec?: number;
logLevel?: 'debug' | 'info' | 'warn' | 'error';
@@ -19,7 +20,7 @@ export function getLivePluginConfig(
const root = (api.config as Record<string, unknown>) || {};
const plugins = (root.plugins as Record<string, unknown>) || {};
const entries = (plugins.entries as Record<string, unknown>) || {};
const entry = (entries['harborforge-monitor'] as Record<string, unknown>) || {};
const entry = (entries['harbor-forge'] as Record<string, unknown>) || {};
const cfg = (entry.config as Record<string, unknown>) || {};
if (Object.keys(cfg).length > 0 || Object.keys(entry).length > 0) {

41
plugin/core/monitor-bridge.d.ts vendored Normal file
View File

@@ -0,0 +1,41 @@
/**
* Monitor Bridge Client
*
* Queries the local HarborForge.Monitor bridge endpoint on MONITOR_PORT
* to enrich plugin telemetry with host/hardware data.
*
* If the bridge is unreachable, all methods return null gracefully —
* the plugin continues to function without Monitor data.
*/
export interface MonitorHealth {
status: string;
monitor_version: string;
identifier: string;
}
export interface MonitorTelemetryResponse {
status: string;
monitor_version: string;
identifier: string;
telemetry?: {
identifier: string;
plugin_version: string;
cpu_pct: number;
mem_pct: number;
disk_pct: number;
swap_pct: number;
load_avg: number[];
uptime_seconds: number;
nginx_installed: boolean;
nginx_sites: string[];
};
last_updated?: string;
}
export declare class MonitorBridgeClient {
private baseUrl;
private timeoutMs;
constructor(port: number, timeoutMs?: number);
health(): Promise<MonitorHealth | null>;
telemetry(): Promise<MonitorTelemetryResponse | null>;
private fetchJson;
}
//# sourceMappingURL=monitor-bridge.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"monitor-bridge.d.ts","sourceRoot":"","sources":["monitor-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE;QACV,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;QACvB,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;QACvB,eAAe,EAAE,OAAO,CAAC;QACzB,WAAW,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;IACF,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAS;gBAEd,IAAI,EAAE,MAAM,EAAE,SAAS,SAAO;IAKpC,MAAM,IAAI,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAIvC,SAAS,IAAI,OAAO,CAAC,wBAAwB,GAAG,IAAI,CAAC;YAI7C,SAAS;CAgBxB"}

View File

@@ -0,0 +1,44 @@
"use strict";
/**
* Monitor Bridge Client
*
* Queries the local HarborForge.Monitor bridge endpoint on MONITOR_PORT
* to enrich plugin telemetry with host/hardware data.
*
* If the bridge is unreachable, all methods return null gracefully —
* the plugin continues to function without Monitor data.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.MonitorBridgeClient = void 0;
class MonitorBridgeClient {
baseUrl;
timeoutMs;
constructor(port, timeoutMs = 3000) {
this.baseUrl = `http://127.0.0.1:${port}`;
this.timeoutMs = timeoutMs;
}
async health() {
return this.fetchJson('/health');
}
async telemetry() {
return this.fetchJson('/telemetry');
}
async fetchJson(path) {
try {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
const response = await fetch(`${this.baseUrl}${path}`, {
signal: controller.signal,
});
clearTimeout(timeout);
if (!response.ok)
return null;
return (await response.json());
}
catch {
return null;
}
}
}
exports.MonitorBridgeClient = MonitorBridgeClient;
//# sourceMappingURL=monitor-bridge.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"monitor-bridge.js","sourceRoot":"","sources":["monitor-bridge.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AA2BH,MAAa,mBAAmB;IACtB,OAAO,CAAS;IAChB,SAAS,CAAS;IAE1B,YAAY,IAAY,EAAE,SAAS,GAAG,IAAI;QACxC,IAAI,CAAC,OAAO,GAAG,oBAAoB,IAAI,EAAE,CAAC;QAC1C,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,MAAM;QACV,OAAO,IAAI,CAAC,SAAS,CAAgB,SAAS,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,IAAI,CAAC,SAAS,CAA2B,YAAY,CAAC,CAAC;IAChE,CAAC;IAEO,KAAK,CAAC,SAAS,CAAI,IAAY;QACrC,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YAErE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,EAAE;gBACrD,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YACH,YAAY,CAAC,OAAO,CAAC,CAAC;YAEtB,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,OAAO,IAAI,CAAC;YAC9B,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAM,CAAC;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;CACF;AAjCD,kDAiCC"}

View File

@@ -0,0 +1,69 @@
/**
* Monitor Bridge Client
*
* Queries the local HarborForge.Monitor bridge endpoint on MONITOR_PORT
* to enrich plugin telemetry with host/hardware data.
*
* If the bridge is unreachable, all methods return null gracefully —
* the plugin continues to function without Monitor data.
*/
export interface MonitorHealth {
status: string;
monitor_version: string;
identifier: string;
}
export interface MonitorTelemetryResponse {
status: string;
monitor_version: string;
identifier: string;
telemetry?: {
identifier: string;
plugin_version: string;
cpu_pct: number;
mem_pct: number;
disk_pct: number;
swap_pct: number;
load_avg: number[];
uptime_seconds: number;
nginx_installed: boolean;
nginx_sites: string[];
};
last_updated?: string;
}
export class MonitorBridgeClient {
private baseUrl: string;
private timeoutMs: number;
constructor(port: number, timeoutMs = 3000) {
this.baseUrl = `http://127.0.0.1:${port}`;
this.timeoutMs = timeoutMs;
}
async health(): Promise<MonitorHealth | null> {
return this.fetchJson<MonitorHealth>('/health');
}
async telemetry(): Promise<MonitorTelemetryResponse | null> {
return this.fetchJson<MonitorTelemetryResponse>('/telemetry');
}
private async fetchJson<T>(path: string): Promise<T | null> {
try {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
const response = await fetch(`${this.baseUrl}${path}`, {
signal: controller.signal,
});
clearTimeout(timeout);
if (!response.ok) return null;
return (await response.json()) as T;
} catch {
return null;
}
}
}