From 7f4921de493a72905b2a1130572256913970817e Mon Sep 17 00:00:00 2001 From: Gmer4Lfe Date: Wed, 26 Aug 2026 17:31:52 -0400 Subject: [PATCH] Give the wizard an assistant scoped to the step you are actually stuck on, so a first-run question can say "this" and mean something --- Plugin/unraid/pages/setup.php | 63 +++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/Plugin/unraid/pages/setup.php b/Plugin/unraid/pages/setup.php index b5ac2fa..30bac92 100644 --- a/Plugin/unraid/pages/setup.php +++ b/Plugin/unraid/pages/setup.php @@ -37,6 +37,12 @@ // Step 2: auto-populate + guide + checklist. // master.conf pull (for partner servers) lives in the checklist, not here. +// The assistant is a bonus on this page, never a dependency: vv_ai_ui_on() is false on a node +// with AI off or no model reachable, which is the normal state of the fresh install this wizard +// exists to serve. The card simply is not rendered and setup proceeds exactly as before. +require_once dirname(__DIR__) . '/include/ai_chat.php'; +if (vv_ai_ui_on()) vv_ai_chat_assets(); + $detectedHostname = vv_get_hostname(); // ── Identity already on disk? ──────────────────────────────────────────────────────────────── @@ -313,6 +319,21 @@ hr.vv-hr { border: none; border-top: 1px solid #1e1e1e; margin: 22px 0; }
+ +
+
+ 'varaverk', + 'compact' => true, + 'title' => 'Setup assistant', + 'height' => '260px', + 'tall' => '460px', + 'empty' => 'Stuck on a step? Ask what it wants and why — "what is the API key for", ' + . '"why does SSH need the other host", "what does populate actually do".', + ]); ?> +
+ +
Skip → @@ -443,6 +464,7 @@ function vvShowStep2(redirect, apiKey) { _vvRedirect = redirect || '?tab=scheduler'; document.getElementById('vv-step1').style.display = 'none'; document.getElementById('vv-step2').style.display = 'block'; + vvSetupAiInit(); // card is visible now, so it can measure itself correctly if (apiKey && apiKey.ok) { const btn = document.getElementById('vv-key-btn'); const status = document.getElementById('vv-key-status'); @@ -676,6 +698,47 @@ function vvStartPhase2Watch(sinceMs) { _vvPartnerPoll = setInterval(check, 6000); } +// ── Setup assistant ─────────────────────────────────────────────────────────── +// Scoped to the step the operator is actually stuck on, so "what does this want" resolves without +// them naming it. The worker turns a non-empty scope into a line saying what is open in the +// WebGUI; the varaverk profile holds no scoped_log capability, so a checklist id never triggers a +// log lookup and cannot produce a "log missing" note for something that was never a script. +// +// Re-read at send time, not captured: the checklist re-polls while the page is open and the step +// they are on can change between opening the composer and pressing Ask. +// +// First not-ok, not-deferred item — deferred means "I have decided to skip this", which is not +// where they are stuck. Falls back to the bare page when the list is clean or has not loaded. +function vvSetupScope() { + const d = _vvLastChecklist; + if (!d || !Array.isArray(d.items)) return 'Setup'; + const stuck = d.items.find(i => !i.ok && !i.deferred); + return stuck && stuck.id ? 'Setup/' + stuck.id : 'Setup'; +} + +// Mounted when Step 2 is revealed, not at parse time. This is the only page where the card starts +// inside a display:none block, and a chat that measured itself while hidden would come up wrong +// with nothing to correct it — the component carries no resize observer. Idempotent because +// vvShowStep2 is reachable more than once. +let _vvSetupAiUp = false; +function vvSetupAiInit() { + if (_vvSetupAiUp) return; + if (typeof VvAiChat !== 'function') return; + if (!document.getElementById('vv-su-ai-chat')) return; // AI off — card was never rendered + _vvSetupAiUp = true; + VvAiChat({ + prefix: 'vv-su-ai', + profile: 'varaverk', + // Pinned, for the same reason the Partnership card pins it: resuming whatever thread was last + // touched anywhere in the UI could land a first-run operator mid-way through someone else's + // Scheduler conversation, on a card with no picker to get back from. + resumeProfile: 'varaverk', + scope: vvSetupScope, + scopeLabel: 'Setup', + empty: 'Stuck on a step? Ask what it wants and why.', + }); +} + function vvLoadChecklist() { fetch('/plugins/varaverk/api/checklist.php?_=' + Date.now()) .then(r => r.json()).then(d => {