diff --git a/Plugin/unraid/README-unraid.md b/Plugin/unraid/README-unraid.md index 602b07a..2dd390c 100644 --- a/Plugin/unraid/README-unraid.md +++ b/Plugin/unraid/README-unraid.md @@ -121,16 +121,23 @@ soon a page notices the writer's update. > cache miss. A key added to the endpoint and not to the writer leaves its card loading forever > on every ordinary page load and working only on the request that happens to miss. -**One widget, rendered twice.** `include/ai_chat.php` owns the conversation surface — profile -bar, transcript, composer, source viewer, stored-chat list — and both the AI tab and the Monitor -tab's AI row construct it. Every id is composed from a prefix so instances can coexist, and each -tears down the previous holder of its prefix, because Unraid swaps tab content by AJAX without -unloading the old page's JavaScript. +**One widget, rendered three times.** `include/ai_chat.php` owns the conversation surface — +transcript, composer, profile and history pickers, source viewer, stored-chat list — and the AI +tab, the Monitor tab's AI row and the Scheduler's right-hand panel all construct it. Every id is +composed from a prefix so instances can coexist, and each tears down the previous holder of its +prefix, because Unraid swaps tab content by AJAX without unloading the old page's JavaScript. -The Scheduler tab's dock is deliberately *not* built on it: a one-line bar that follows the view -you have open, with its own scope chip, fix flow and incident capture, is a different component -that happens to share an endpoint. Folding it in would produce one widget with two personalities -and a mode flag choosing between them. +A placement chooses how much room it gets and which extra controls it needs. It does not choose +the shape: the control row is fixed everywhere — profile chip hard left, `⤢` `▾` `New` `Ask` hard +right — because a chat that rearranges itself per tab is three components wearing one name. + +The Scheduler panel was exactly that until it was folded in, and it proved the cost: a thread +there died on reload while the other two were saved, and its bar had drifted into a different +shape from the same control everywhere else. What was genuinely particular to it became options +rather than a second implementation — `scope` as a function for a subject that follows the open +view, `beforeSend` for the one reply that is recorded rather than asked, `think` for reasoning on +diagnosis only, and `setHeights()` for a placement sized as a share of a panel, which is not a +number that exists until layout has run. **Timezone.** `include/config.php` adopts Unraid's own `timeZone` from `ident.cfg` for the whole PHP layer. PHP here has no `date.timezone` and therefore ran in UTC while the server ran local, diff --git a/Plugin/unraid/include/ai.php b/Plugin/unraid/include/ai.php index 93569cc..314c7ed 100644 --- a/Plugin/unraid/include/ai.php +++ b/Plugin/unraid/include/ai.php @@ -90,7 +90,7 @@ require_once __DIR__ . '/config.php'; const VV_AI_KINDS = ['header', 'readme', 'manual', 'template', 'doc', 'ui']; // Profiles — what each one is, and what it is allowed to see and do. One table, in one file, -// read by everything: this endpoint, the worker, the shared chat include and the Scheduler dock. +// read by everything: this endpoint, the worker, and the shared chat include every page renders. // vv_ai_profile_can() and friends come from there. require_once __DIR__ . '/ai_profiles.php'; @@ -816,7 +816,7 @@ function vv_ai_token_stats(): array { return $out; } -// ── Scoped lookups for the WebGUI dock ─────────────────────────────────────────────────────── +// ── Scoped lookups for the Scheduler's assistant ────────────────────────────────────────────── // The tail of one named script's log, for the troubleshooting profile. vv_ai_recent_logs() // answers "is anything wrong anywhere"; this answers "why did THIS fail", which is a different @@ -1308,11 +1308,11 @@ function vv_ai_chat_save(string $id, string $profile, array $messages, string $s $prev = vv_ai_chat_read($id); $created = (int)($prev['created'] ?? time()); - // Scope travels with the conversation. A Scheduler dock thread is bound to what the operator - // had open — a script, a log, a conf key — and its turns carry log excerpts chosen for that + // Scope travels with the conversation. A Scheduler thread is bound to what the operator had + // open — a script, a log, a conf key — and its turns carry log excerpts chosen for that // thing. Storing the scope means reopening the thread anywhere restores the context it was // reasoned in, rather than silently continuing a troubleshooting conversation against - // whatever happens to be on screen. The isolation the dock enforces in memory becomes a + // whatever happens to be on screen. The isolation the page enforces in memory becomes a // property of the record instead of something lost the moment it is saved. $rec = [ 'id' => $id, diff --git a/Plugin/unraid/include/ai_profiles.php b/Plugin/unraid/include/ai_profiles.php index 04d25f7..52c8c78 100644 --- a/Plugin/unraid/include/ai_profiles.php +++ b/Plugin/unraid/include/ai_profiles.php @@ -2,7 +2,8 @@ // ═══════════════════════════════════════════════════════════════════════════════════════════════ // PURPOSE // The one definition of what an AI profile is. Every consumer — the endpoint, the worker, the -// shared chat include, the Scheduler dock — reads it from here instead of restating it. +// shared chat include and every page that renders it — reads it from here instead of +// restating it. // // WHY THIS EXISTS // A profile used to be defined in five places: history depth in api/ai.php, capabilities in @@ -187,9 +188,9 @@ function vv_ai_profiles_client(): array { // surfaces ask for it. Emitted as its own tag so any script block that consumes it stays pure // JavaScript and remains syntax-checkable outside PHP. // -// Both the shared chat include and the Scheduler dock call this. Before it existed the dock had -// its own literal `{ code: 'Code', troubleshoot: 'Troubleshoot' }` map, which is how a fourth -// copy of the profile list came to exist in the first place. +// The shared chat include calls this, as does any page emitting the registry ahead of it. Before +// it existed the Scheduler had its own literal `{ code: 'Code', troubleshoot: 'Troubleshoot' }` +// map, which is how a fourth copy of the profile list came to exist in the first place. function vv_ai_profiles_script(): void { static $done = false; if ($done) return; diff --git a/Plugin/unraid/pages/monitor.php b/Plugin/unraid/pages/monitor.php index b463473..8a8d04a 100644 --- a/Plugin/unraid/pages/monitor.php +++ b/Plugin/unraid/pages/monitor.php @@ -356,8 +356,9 @@ $_vv_doc_vars = array_merge(vv_conf_vars(), ['SCRIPTS_DIR' => SCRIPTS_DIR]); - +

diff --git a/Plugin/unraid/pages/readme/monitor-readme.md b/Plugin/unraid/pages/readme/monitor-readme.md index ed5ac07..db9d3a9 100644 --- a/Plugin/unraid/pages/readme/monitor-readme.md +++ b/Plugin/unraid/pages/readme/monitor-readme.md @@ -56,11 +56,13 @@ as the GPU and UPS cards. | Card | What it tells you | |---|---| -| AI | Model residency, context size, VRAM, index size and staleness, tokens used today | +| AI | Model residency, context size, VRAM, index size and staleness | +| Tokens | What the assistant has spent — per node, and for today, the last 7 days and all time | | Conversations | The last `$AI_CHAT_HISTORY_MAX` chats. Click to reopen, × to delete | | Assistant | Ask a question without leaving the dashboard | -| ⤢ | Expands the conversation to about two and a half times its height. Remembered | -| Profile buttons | Which contract answers — General Chat, Varaverk Assistant, Code Sketcher, Troubleshoot | +| Profile chip | Which contract answers — General Chat, Varaverk Assistant, Code Sketcher, Troubleshoot | +| ⤢ | Trades more room for the conversation, and back. Always opens at the smaller size | +| ▾ | Saved conversations, the same ones the Conversations card lists | --- @@ -79,6 +81,25 @@ implied. These figures come from the same one-minute collection the AI tab's banner uses, so the two cannot disagree about whether the model is loaded. +## Tokens is its own card, not a line on the AI one + +The AI card answers whether the model is healthy right now. What it has spent over a month is a +different question, and it was crowding that card out one line at a time. + +`Nodes` lists each host with its total. A host with no rows reads **not collected here**, never +zero — each host writes to its own `data/` and only `ai_token_sync.sh` moves a ledger between +them, so a zero would claim the partner sat idle when the truth is that this host cannot see its +ledger at all. Click a node to scope the figures below it to that host; click **All hosts** to go +back. + +The totals cover today, the last 7 days and all time, each with the turn count and the prompt / +completion split. The footer adds how long the ledger has been running, the best throughput seen, +and — under All hosts only — the split by profile and by source. Those last two describe the whole +ledger, so they are not shown under a single host's heading where they would not describe it. + +This is the same ledger the AI tab shows, read from the same endpoint. It refreshes when a turn +finishes here, and otherwise once a minute, because the numbers only move when a turn completes. + ## The assistant here starts on General Chat The AI tab starts on Varaverk Assistant, which answers only from this installation's @@ -91,7 +112,7 @@ to the strict profile automatically, and handed back if the documentation turns it. Starting strict would refuse ordinary questions to guard against a mistake the server already prevents. -Switching profile with the buttons keeps what is on screen but stops sending earlier turns to the +Switching profile with the chip keeps what is on screen but stops sending earlier turns to the model. Carrying cited, retrieval-grounded answers into a mode with no retrieval makes the model keep referring to sources it can no longer see. diff --git a/Plugin/unraid/pages/readme/scheduler-readme.md b/Plugin/unraid/pages/readme/scheduler-readme.md index e11f337..9ea7513 100644 --- a/Plugin/unraid/pages/readme/scheduler-readme.md +++ b/Plugin/unraid/pages/readme/scheduler-readme.md @@ -80,6 +80,42 @@ Two blocks on the Scheduler Info panel get you there faster: The status dot in the Orch tree is green, orange or red for the last run's outcome, dim if the script has never run. Hover for detail. +## Asking the assistant about what is on screen + +The panel below the right-hand views is the same chat component the AI tab and the Monitor +dashboard use, at this panel's size. What is particular to this tab is that its subject follows +you: open a log, a conf or a script and the chip states both the profile answering and the thing +it is pointed at. Nothing is inferred silently — if what the chip says is wrong, that costs a +glance rather than a confidently wrong answer. + +Every row in **Recent Activity** carries a **why?** (failed) or **recap** (clean) button. It opens +that script's log first and then asks, because the question is only worth asking with the log +attached — the profile that reads it is the one that gets the log tail. The question is posted as +visible text, so what was asked on your behalf is never a mystery. + +Moving to a different subject keeps the transcript on screen but stops sending the earlier turns +to the model, and starts a new stored conversation. A troubleshooting thread carrying log excerpts +must not bleed into a question about a conf key; hiding that the earlier exchange happened would +be worse than carrying it visibly. + +Reasoning is enabled only for Troubleshoot. Working out what a log means is worth waiting for; a +lookup like "what does this setting do" is not, and an inline answer that stalls reads as broken. + +## Recording what actually fixed something + +When a diagnosis is followed by that same script running clean, the assistant offers to record it: +*"`