diff --git a/Assets/assistent.js b/Assets/assistent.js index 0925fc2..d8574ae 100644 --- a/Assets/assistent.js +++ b/Assets/assistent.js @@ -1,6 +1,6 @@ /** * Swarm Assistent — Krea 2 collaborative chat (Ollama via Swarm API). - * v0.7.0: Config presets, persona folders, exact KV + vector memory, chat|memory model roles. + * v0.7.1: Exact KV memory; block SwarmUI ViewSpecial/model-card previews from Generate+vision. */ (function () { const LS_BASE = 'swarm_assistent_base_url'; @@ -667,7 +667,7 @@ return state.slots.filter((s) => s.attach && s.src); } - function setSlotSrc(id, src, { select = true, attach = null, note = null, switchTab = false } = {}) { + function setSlotSrc(id, src, { select = true, attach = null, note = null, switchTab = false, allowPreview = false } = {}) { const slot = slotById(id); if (!slot) { return false; @@ -676,6 +676,10 @@ if (cleaned && cleaned.startsWith('#')) { return false; } + if (cleaned && !allowPreview && looksLikeModelPreview(cleaned)) { + setStatus('Пропуск превью модели (нужна реальная генерация)'); + return false; + } slot.src = cleaned || null; if (attach != null) { slot.attach = !!attach; @@ -745,9 +749,12 @@ } function snapshotGenerateToRef() { - const src = generateSlot()?.src || findCurrentGenerateSrc({ allowPreview: true }); + // Never promote checkpoint/LoRA card previews into Refs. + const src = generateSlot()?.src && !looksLikeModelPreview(generateSlot().src) + ? generateSlot().src + : findCurrentGenerateSrc({ allowPreview: false }); if (!src) { - setStatus('Нет текущего кадра Generate'); + setStatus('Нет текущего кадра Generate (превью модели не считается)'); return false; } const empty = refSlots().find((s) => !s.src); @@ -1120,11 +1127,15 @@ } function syncGenerateSlot() { - const src = findCurrentGenerateSrc(); const slot = generateSlot(); if (!slot) { return; } + // Drop checkpoint/LoRA card previews that slipped into the Generate pane. + if (scrubPreviewFromGenerateSlot()) { + renderBoard(); + } + const src = findCurrentGenerateSrc(); if (src && src !== slot.src) { slot.src = src; const img = document.querySelector('.sa-slot-gen img'); @@ -1140,6 +1151,17 @@ empty.hidden = true; } frame?.classList.add('sa-has-image'); + } else if (!src && !slot.src) { + const empty = document.querySelector('.sa-slot-gen .sa-image-empty'); + const frame = document.querySelector('.sa-slot-gen'); + const img = document.querySelector('.sa-slot-gen img'); + if (img) { + img.remove(); + } + if (empty) { + empty.hidden = false; + } + frame?.classList.remove('sa-has-image', 'sa-attached'); } syncGenerateBusy(); syncPatchActionAvailability(); @@ -2824,9 +2846,17 @@ if (!s) { return false; } - return s.includes('.preview.') + // SwarmUI checkpoint/LoRA cards: ViewSpecial/*, View/Models/*, *.preview.*, PLACEHOLDER. + if (s.includes('.preview.') || s.includes('placeholder') - || /\/models\//i.test(s); + || s.includes('/viewspecial/') + || s.includes('viewspecial/') + || s.includes('/models/') + || s.includes('view/models/') + || /[?&](?:path|file)=[^&]*\.preview\./i.test(s)) { + return true; + } + return false; } function findCurrentGenerateSrc({ allowPreview = false } = {}) { @@ -2837,7 +2867,7 @@ || document.querySelector('.current-image img') || document.querySelector('#current_image_batch img'); if (cur) { - src = cur.dataset?.src || cur.src || null; + src = cur.dataset?.src || cur.getAttribute?.('data-src') || cur.src || null; } } catch (e) { /* ignore */ } if (!src) { @@ -2850,20 +2880,38 @@ if (!src) { return null; } + // Strip cache-busters for classification, keep original for display when accepted. if (!allowPreview && looksLikeModelPreview(src)) { return null; } return src; } + function scrubPreviewFromGenerateSlot() { + const slot = generateSlot(); + if (!slot?.src) { + return false; + } + if (!looksLikeModelPreview(slot.src)) { + return false; + } + slot.src = null; + slot.attach = false; + syncLastImageAlias(); + return true; + } + function refreshImagePreview() { + scrubPreviewFromGenerateSlot(); if (wantsAutoVision()) { const gen = generateSlot(); if (gen) { - gen.attach = true; const src = findCurrentGenerateSrc(); if (src) { + gen.attach = true; gen.src = src; + } else { + gen.attach = false; } renderBoard(); } @@ -4409,7 +4457,8 @@ if (!ids.length || state.visionHopUsed) { return false; } - const have = ids.map((id) => slotById(id)).filter((s) => s && s.src); + scrubPreviewFromGenerateSlot(); + const have = ids.map((id) => slotById(id)).filter((s) => s && s.src && !looksLikeModelPreview(s.src)); if (!have.length) { const genSrc = findCurrentGenerateSrc(); if (ids.includes(GEN_ID) && genSrc) { @@ -4421,7 +4470,7 @@ } } if (!have.length) { - setStatus('look_at: those windows are empty'); + setStatus('look_at: нет реального кадра (превью модели пропущено)'); return false; } const already = new Set(attachedSlotIds || []); @@ -4521,10 +4570,10 @@ if (!wantedIds.length) { wantedIds = attachableSlots().map((s) => s.id); } - if (wantsAutoVision() && generateSlot()?.src && !wantedIds.includes(GEN_ID)) { + if (wantsAutoVision() && generateSlot()?.src && !looksLikeModelPreview(generateSlot().src) && !wantedIds.includes(GEN_ID)) { wantedIds.push(GEN_ID); } - const visionSlots = wantedIds.map((id) => slotById(id)).filter((s) => s && s.src); + const visionSlots = wantedIds.map((id) => slotById(id)).filter((s) => s && s.src && !looksLikeModelPreview(s.src)); let images = null; if (visionSlots.length) { startBusyUi('encoding'); diff --git a/Config/_base/core/core.md b/Config/_base/core/core.md index 9e4c685..22ab538 100644 --- a/Config/_base/core/core.md +++ b/Config/_base/core/core.md @@ -6,7 +6,7 @@ You are **Swarm Assistent**, a collaborative art director for image generation i When instructions conflict, apply this order (highest wins): -1. **This core contract** — output format, never invent LoRA/checkpoint names, never use CFG 0. +1. **This core contract** — output format, never invent LoRA/checkpoint names, never use CFG 0, never depict or request anyone 17 or under (adults only). 2. **Current user message** — explicit “use steps 20 / aspect 16:9 now” wins for that turn. 3. **Live `session_exact`** — prior user overrides this chat (until persona change / clear chat). 4. **Exact memory** (`## Exact memory` JSON) — canonical defaults (steps/CFG/aspect/facts). Persona overlays are already merged into it. diff --git a/README.md b/README.md index 3073b44..cccb8be 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ SwarmUI extension for **collaborative Krea 2** prompting via **Ollama**: chat + board (Generate | Refs tabs), LoRA chips, **persona presets** (`Config/personas/`), **vector memory**, model cards with Civitai fetch, img2img/inpaint, slash commands, auto Generate. -**Version 0.7.0** — Config/_base + persona folders, skills, **exact KV memory** + vector memory-seed → SQLite, Ollama `use: chat|memory`, slim inventory via retrieve. +**Version 0.7.1** — Exact KV memory + persona overlays; block SwarmUI `ViewSpecial`/model-card previews from Generate + vision. ## Layout diff --git a/SwarmAssistentExtension.cs b/SwarmAssistentExtension.cs index c8c7ec5..c7ebaa2 100644 --- a/SwarmAssistentExtension.cs +++ b/SwarmAssistentExtension.cs @@ -49,7 +49,7 @@ public class SwarmAssistentExtension : Extension ExtensionAuthor = "mrleo1nid"; Description = "Collaborative Krea 2 assistant: Ollama chat, persona presets, vector memory, model cards, Generate loop."; License = "MIT"; - Version = "0.7.0"; + Version = "0.7.1"; Tags = ["tabs", "ui", "llm", "ollama", "krea", "inpaint", "memory"]; }