Let troubleshoot see the machine and answer with a route
It could describe a conf edit but not the switch that makes it, and knew nothing about containers, pools or the array it was reasoning about.
This commit is contained in:
@@ -1372,6 +1372,87 @@ function vv_ai_bug_report(array $b): string {
|
||||
return $out;
|
||||
}
|
||||
|
||||
// The machine as it is right now — hardware, containers, storage — summarised small enough to
|
||||
// sit in a prompt.
|
||||
//
|
||||
// Read from the cache the WebGUI already writes every minute rather than measured here. A
|
||||
// question must not cost a docker ps across fifty containers plus a disk sweep; the numbers move
|
||||
// on their own schedule and one minute stale is the same answer. The age is stated so the model
|
||||
// can say "a minute ago" rather than implying it looked just now.
|
||||
//
|
||||
// Strictly read-only, and there is no counterpart that changes any of it. Knowing a container is
|
||||
// down is what lets an explanation be about this machine instead of about Unraid in general;
|
||||
// restarting it is a decision that belongs to a person looking at the screen.
|
||||
function vv_ai_system_state(): string {
|
||||
$p = '/tmp/varaverk/api/monitor.json';
|
||||
if (!is_readable($p)) return '';
|
||||
$d = json_decode((string) @file_get_contents($p), true);
|
||||
if (!is_array($d)) return '';
|
||||
|
||||
$age = time() - (int) @filemtime($p);
|
||||
$s = "LIVE MACHINE STATE (read-only, measured " . ($age < 90 ? 'under a minute' : round($age / 60) . ' minutes')
|
||||
. " ago — you cannot change any of it)\n";
|
||||
|
||||
$sys = $d['system'] ?? [];
|
||||
if ($sys) {
|
||||
$s .= '- host: ' . ($sys['cpu_model'] ?? '?') . ', ' . ($sys['cpu_threads'] ?? '?') . " threads\n";
|
||||
}
|
||||
if (!empty($d['cpu']['overall'])) $s .= '- cpu: ' . $d['cpu']['overall'] . "% overall\n";
|
||||
|
||||
$r = $d['resources'] ?? [];
|
||||
if (!empty($r['ram_total_mb'])) {
|
||||
$used = (int) $r['ram_total_mb'] - (int) ($r['ram_free_mb'] ?? 0);
|
||||
$s .= sprintf("- memory: %d of %d MB used\n", $used, (int) $r['ram_total_mb']);
|
||||
}
|
||||
|
||||
foreach ((array) ($d['gpus'] ?? []) as $g) {
|
||||
$s .= sprintf("- gpu %d: %s, %d/%d MB, %d%% util, %d°C\n", $g['index'] ?? 0, $g['name'] ?? '?',
|
||||
$g['memory_used'] ?? 0, $g['memory_total'] ?? 0, $g['utilization'] ?? 0,
|
||||
$g['temperature'] ?? 0);
|
||||
}
|
||||
|
||||
// Named individually only when something is wrong with them. Fifty healthy container names is
|
||||
// the bulk of this block and none of it is ever the answer; the handful that are not are.
|
||||
//
|
||||
// Taken from the payload's own `stopped` list rather than derived. There is no state field on
|
||||
// a container row — only `status`, which reads "Up 15 hours (healthy)" — so an earlier version
|
||||
// of this looked for "run", found it nowhere, and reported all fifty as down. A block that
|
||||
// confidently lists healthy containers as stopped is worse than no block: it is exactly the
|
||||
// sort of thing the model would build a whole wrong explanation on.
|
||||
$ctrs = (array) ($d['containers'] ?? []);
|
||||
$stopped = (array) ($d['stopped'] ?? []);
|
||||
$down = array_values(array_filter(array_map(
|
||||
fn($c) => trim((string) (is_array($c) ? ($c['name'] ?? '') : $c)), $stopped)));
|
||||
|
||||
// Up, but failing its own healthcheck. Running is not the same as working, and this is the
|
||||
// state that produces "it is started, so why is nothing happening".
|
||||
$sick = [];
|
||||
foreach ($ctrs as $c) {
|
||||
if (stripos((string) ($c['status'] ?? ''), 'unhealthy') !== false) $sick[] = (string) ($c['name'] ?? '?');
|
||||
}
|
||||
|
||||
$s .= '- containers: ' . count($ctrs) . ' running';
|
||||
$s .= $down ? ', STOPPED: ' . implode(', ', array_slice($down, 0, 12)) : ', none stopped';
|
||||
$s .= $sick ? '; UNHEALTHY: ' . implode(', ', array_slice($sick, 0, 8)) : '';
|
||||
$s .= "\n";
|
||||
|
||||
foreach ((array) ($d['storage'] ?? []) as $pool) {
|
||||
if (empty($pool['name'])) continue;
|
||||
$s .= sprintf("- pool %s: %s%% used\n", $pool['name'], $pool['used_pct'] ?? $pool['pct'] ?? '?');
|
||||
}
|
||||
|
||||
$par = $d['parity'] ?? [];
|
||||
if ($par) {
|
||||
$s .= '- array: ' . (($par['num_missing'] ?? 0) ? $par['num_missing'] . ' disks MISSING' : 'no missing disks')
|
||||
. (($par['num_disabled'] ?? 0) ? ', ' . $par['num_disabled'] . ' disabled' : '')
|
||||
. (!empty($par['in_progress']) ? ', parity operation in progress' : '') . "\n";
|
||||
}
|
||||
if (!empty($d['ups']['available'])) {
|
||||
$s .= '- ups: ' . ($d['ups']['status'] ?? '?') . "\n";
|
||||
}
|
||||
return $s . "\n";
|
||||
}
|
||||
|
||||
// Where a report can go from this install, resolved once so the page and the sender agree.
|
||||
//
|
||||
// Local is opt-in and off by default, because a default that files into the operator's own
|
||||
|
||||
Reference in New Issue
Block a user