diff --git a/Plugin/unraid/Tools/ai_chat_worker.php b/Plugin/unraid/Tools/ai_chat_worker.php index 1c49236..de0c44c 100644 --- a/Plugin/unraid/Tools/ai_chat_worker.php +++ b/Plugin/unraid/Tools/ai_chat_worker.php @@ -82,8 +82,8 @@ if (PHP_SAPI !== 'cli') { require_once dirname(__DIR__) . '/include/ai.php'; -[$jobFile, $question, $historyJson, $kind, $think, $profile] = - array_slice($argv, 1, 6) + array_fill(0, 6, ''); +[$jobFile, $question, $historyJson, $kind, $think, $profile, $scope] = + array_slice($argv, 1, 7) + array_fill(0, 7, ''); if ($jobFile === '' || $question === '') exit(1); if (!preg_match('#/[0-9a-f]{32}\.json$#', $jobFile)) exit(1); @@ -240,6 +240,22 @@ if ($profile === 'chat') { // has already been decided — so it should frame everything that follows rather than read as one // more retrieved document. Marked as operator-authored so the model treats it as fact about the // installation rather than as a source to cite. +// Where the operator is standing in the WebGUI. Sent by the scheduler page, absent from the AI +// tab, which has no location to speak of. It is what lets "what does this do" resolve — without +// it the model has to guess which of 120 settings "this" means, and it will guess confidently. +// +// Stated as context, never as an instruction to trust: the file named here is where to look +// first, not proof that the answer is in it. That distinction is the whole point of the +// fallback — a setting the operator expects in master.conf may actually live in the host conf, +// and saying so is more useful than failing to find it. +if ($scope !== '') { + $system .= "WHERE THE OPERATOR IS RIGHT NOW\n" + . "They have " . $scope . " open in the WebGUI. Read bare references — \"this " + . "setting\", \"this script\", \"here\" — as meaning that unless they clearly mean " + . "something else. Look there first. If what they are asking about is genuinely " + . "somewhere else, answer anyway and tell them plainly where it actually is.\n\n"; +} + $mem = vv_ai_memory_read(); if ($mem['exists'] && trim($mem['text']) !== '') { $system .= "WHAT YOU ALREADY KNOW ABOUT THIS OPERATOR AND INSTALLATION\n" diff --git a/Plugin/unraid/api/ai.php b/Plugin/unraid/api/ai.php index 47cab86..62e8fdc 100644 --- a/Plugin/unraid/api/ai.php +++ b/Plugin/unraid/api/ai.php @@ -210,6 +210,16 @@ if ($action === 'ask') { } $maxTurns = VV_AI_PROFILES[$profile] ?? VV_AI_MAX_TURNS; + // Where the caller is standing — "master.conf", "daily_sync_maintenance.sh", a log name. + // The scheduler page sends it so a question can say "this setting" and mean something; the + // AI tab sends nothing and the worker simply omits the location line. + // + // Whitelisted hard, not escaped and hoped for. It reaches the model as text, so anything + // richer than a file name is an instruction-injection surface for no benefit — a scope is + // only ever a name from this page's own view state. + $scope = trim($_POST['scope'] ?? ''); + if ($scope !== '' && !preg_match('#^[A-Za-z0-9 ._/-]{1,80}$#', $scope)) $scope = ''; + // The retrieval filter only means anything to the profile that retrieves. $kind = $profile === 'varaverk' ? trim($_POST['kind'] ?? '') : ''; if ($kind !== '' && !in_array($kind, VV_AI_KINDS, true)) { @@ -259,7 +269,8 @@ if ($action === 'ask') { . escapeshellarg(json_encode($clean)) . ' ' . escapeshellarg($kind) . ' ' . escapeshellarg(($_POST['think'] ?? '1') === '1' ? '1' : '0') . ' ' - . escapeshellarg($profile) + . escapeshellarg($profile) . ' ' + . escapeshellarg($scope) . ' >/dev/null 2>&1 SCRIPTS_DIR, ]); +// The assistant dock renders only where the AI tab itself would: HOST1, with AI_ENABLED true. +// Same two conditions, checked the same way, so the page cannot offer a chat the endpoint will +// refuse — api/ai.php 404s every action off HOST1 regardless of what this page draws. +$_vv_ai_on = vv_is_ai_host() + && strtolower(trim(vv_conf_vars()['AI_ENABLED'] ?? 'false')) === 'true'; + // Setup mode — auto-open a conf file and force the editing sequence $vv_setup_conf = preg_match('/^[\w.]+\.conf$/', $_GET['vv_setup'] ?? '') ? $_GET['vv_setup'] : ''; @@ -1040,6 +1046,27 @@ Still the same two servers, two households, the same media stack running itself. + + +
+ +
+ Assistant · Scheduler + + + +
+
+