diff --git a/CHANGELOG.md b/CHANGELOG.md index 5006c11e7..30b2695fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ This file is the release-notes source of truth for Marinara Engine. Reuse these - Added a Marinara-specific AI agent workflow overlay, adapted from the Chai Agent Workflow Pack, covering proof discipline, bugfix/feature lanes, issue filing, PR gates, and risky-work claim boundaries. - Added a None option for Roleplay message avatars so messages can render without avatar attachments. +- Added default starting values for numeric Game HUD widgets, with setup/editor clamps that keep start values within the configured max. +- Added a prompt override editor for registered prompt templates, including conversation selfie overrides, collapsible settings, and draft preservation. +- Added shared drag-and-drop image upload dropzones for character avatars, chat gallery images, and background imports. - Added a manual Game Mode combat start control with confirmation so players can trigger encounter setup when a scene should enter combat. - Added a General quote-format preference for straight or curly dialogue quotes and apostrophes, with editor/input formatting support across chat, presets, characters, and personas. - Added conditional prompt macros, macro comment blocks, and Macro Reference guidance so presets and character/persona cards can keep author-only notes or branch prompt text by speaker/character. @@ -29,6 +32,8 @@ This file is the release-notes source of truth for Marinara Engine. Reuse these - Removed the Conversation, Roleplay, and Game mode shortcuts from the topbar because the sidebar already owns mode navigation. - Widened the Glued Side Panel roleplay avatar presentation so the portrait strip has more visual presence. +- Improved sprite wand cleanup with halo edge cleanup, clean/paint brush tools, unified brush controls, and better multi-pointer handling. +- Polished Tracker Panel visual controls, thought bubbles, persona/tracker card styling, responsive world-state temperature display, and color preview restore/legacy tint behavior. - Improved Game Mode combat setup so encounter generation can run in the background after scene analysis, with debug logging and a wait state only when the player reaches combat before setup is ready. - Removed unreliable met/unmet status tracking from Game Mode NPC prompt context. - Improved Roleplay group chat Individual mode prompting so only the currently responding character card is included, other characters' prior messages are treated as user-side context, and the turn-owner instruction can be toggled. @@ -44,9 +49,15 @@ This file is the release-notes source of truth for Marinara Engine. Reuse these ### Fixed +- Fixed mobile Conversation chats where optional toolbar actions could squeeze the message textarea down until it appeared missing on narrow phone viewports. +- Fixed tracker character-card lookup so active-chat card aliases from title/comment text resolve tracker rows before out-of-chat fallback cards, keeping group-chat tracker portraits and color settings attached to the intended character. +- Fixed character tracker refreshes preserving user-uploaded NPC portraits and portrait framing across agent updates, including first snapshot writes. +- Fixed the Roleplay HUD temperature chip so it respects the shared Tracker Panel Celsius/Fahrenheit display setting. - Added a stale client artifact cleanup step for the obsolete tracker data sidebar folder so installs, updates, checks, and builds are not tripped up by leftover local files after the tracker panel refactor. - Fixed Docker builds so the stale client artifact cleanup script is available before dependency install/build scripts run. - Fixed streaming Roleplay messages in Glued Side Panel avatar mode so the avatar frame keeps the selected scale and is revealed by the growing message instead of rescaling while tokens arrive. +- Fixed Quest Board state merges so tracker updates no longer revert quest progress or keep completed empty-objective quests. +- Fixed profile export/import fallback handling for large assets so profile exports can recover cleanly when embedded asset payloads are too large. - Fixed Windows installer updates for existing shallow release checkouts by fetching the resolved release commit before checkout. - Fixed mobile Game Mode character and party controls so sheet actions stay compact, long character names can remain accessible, and crowded party rosters collapse into a scrollable mobile party picker. - Fixed mobile Game Mode choice prompts so large choice sets stay readable and scroll inside the available play area instead of squishing buttons or pushing custom input off-screen. @@ -81,6 +92,8 @@ This file is the release-notes source of truth for Marinara Engine. Reuse these - Added explicit Illustrator try-again controls when image generation fails, including a toast action and a persistent Roleplay HUD retry button. ([#797](https://github.com/Pasta-Devs/Marinara-Engine/issues/797)) - Added Local Model sidecar as a first-class embedding source, including an Embedding Connection option, lorebook vectorization support, and a stable `/api/sidecar/v1/embeddings` endpoint. ([#780](https://github.com/Pasta-Devs/Marinara-Engine/issues/780)) - Added opt-in Turn Data Access settings for custom post-processing agents so they can receive current-turn pre-generation injections and parallel agent results without exposing that data to existing agents by default. ([#778](https://github.com/Pasta-Devs/Marinara-Engine/issues/778)) +- Added Memory Recall export/import for moving chat recall data between profiles or installs. +- Added weighted random macro choices for SillyTavern-style random prompt variants. - Added a native Appearance background blur slider for Roleplay and Game mode backgrounds. ([#763](https://github.com/Pasta-Devs/Marinara-Engine/issues/763)) - Added excluded-tag filtering for the character browser, including `-tag:"tag name"` search syntax and exclude toggles in the character tag picker. ([#702](https://github.com/Pasta-Devs/Marinara-Engine/issues/702)) - Added a server-side autonomous conversation scheduler so enabled characters can generate restrained scheduled messages while the browser poller is absent, with client-presence checks to avoid duplicate client/server generations. ([#698](https://github.com/Pasta-Devs/Marinara-Engine/issues/698)) @@ -124,6 +137,8 @@ This file is the release-notes source of truth for Marinara Engine. Reuse these - Fixed Game Mode asset generation prompt review, NPC portrait matching, sprite recovery, Professor-name avatar matching, and command-prompt regeneration replay. - Fixed Game Session Log flicker, deletion offsets, manual deletion persistence, and dice-roll dismissal when advancing dialogue. - Fixed Game Mode weather, storm ambience, sun overlay behavior, CYOA live updates, skill checks, inventory notifications, combat voice audio, mobile party access, tracker refreshes, and tracker edit persistence. +- Fixed CJK Google font shard loading and scene-summary max-token overrides. +- Fixed manual chat file deletion persistence and regenerate replay for command prompts. - Fixed Conversation disconnection aborts on Docker, markdown block preservation, hidden-message regeneration crashes, Up Arrow recall behavior, role editing, DM schedule inheritance, random connection schedule generation, and connected-chat placeholder branch names. - Fixed character avatar uploads preserving unsaved drafts, chat folder click targets, drag reorder behavior, text selection while dragging, folder storage atomicity, and Professor Mari continuation after tool/fetch work. - Fixed OpenAI ChatGPT request shape and SSE parsing, compressed provider JSON decoding (`gzip`, raw `gzip`, and Brotli), Gemini gzip decoding, provider identity handling, NovelAI V4 prompt/model handling, ComfyUI numeric workflow placeholders, Horde image endpoints, and Pygmalion avatar content-type fallback. @@ -154,6 +169,7 @@ This file is the release-notes source of truth for Marinara Engine. Reuse these - Per-connection max parallel agent job controls, allowing agent-heavy chats to split same-connection work across multiple LLM calls. - Editable Game Session History map JSON in the current-session spoiler section. - Markdown rendering and live preview for Game journal notes. +- Tracker Data Sidebar for viewing and editing live tracker data from the side panel. - `/emote name="Character" expression="expression"` for listing and manually switching roleplay sprite expressions. - Duplicate action for individual prompt preset blocks. - Close controls for Game mode choice prompts and quick-time event windows. diff --git a/packages/client/src/components/chat/ConversationInput.tsx b/packages/client/src/components/chat/ConversationInput.tsx index 1b4e29fab..3c6792e9b 100644 --- a/packages/client/src/components/chat/ConversationInput.tsx +++ b/packages/client/src/components/chat/ConversationInput.tsx @@ -1569,7 +1569,7 @@ export function ConversationInput({ onDragLeave={handleDragLeave} onDrop={handleDrop} className={cn( - "relative flex items-center gap-1 rounded-2xl border-2 bg-[var(--card)] px-2 py-1.5 transition-all duration-200 sm:gap-2 sm:px-4 sm:py-2.5 dark:bg-black/40", + "relative flex flex-wrap items-end gap-1 rounded-2xl border-2 bg-[var(--card)] px-2 py-1.5 transition-all duration-200 sm:flex-nowrap sm:items-center sm:gap-2 sm:px-4 sm:py-2.5 dark:bg-black/40", isDragging ? "border-blue-400/50 bg-blue-500/10 shadow-lg shadow-blue-500/10" : "border-[var(--border)]", )} > @@ -1588,7 +1588,7 @@ export function ConversationInput({ @@ -1567,26 +1569,6 @@ function getWeatherEmoji(weather: string): string { return "🌀️"; } -function parseTemperature(temp: string): number | null { - const m = temp.match(/-?\d+(\.\d+)?/); - if (!m) return null; - const num = parseFloat(m[0]!); - if (/Β°?\s*f/i.test(temp)) return Math.round((num - 32) * (5 / 9)); - return Math.round(num); -} - -/** Map descriptive temperature words to a numeric-equivalent hint (Β°C). */ -function getTemperatureKeywordHint(text: string): number | null { - const t = text.toLowerCase(); - if (/\b(freez|frigid|arctic|glacial|sub-?zero|blizzard)/.test(t)) return -10; - if (/\b(cold|chill|frost|wintry|icy|bitter|nipp)/.test(t)) return 2; - if (/\b(cool|brisk|crisp|refresh)/.test(t)) return 12; - if (/\b(mild|pleasant|comfort|temperate|fair)/.test(t)) return 20; - if (/\b(warm|balmy|toasty|muggy|humid|stuffy|sultry)/.test(t)) return 28; - if (/\b(hot|swelter|blaz|scorch|burn|heat|boil|sear|bak)/.test(t)) return 38; - return null; -} - /** Categorise location text into a colour for the map-pin icon. */ function getLocationPinColor(location: string): string { const l = location.toLowerCase(); diff --git a/packages/client/src/components/lorebooks/LorebookFormFields.tsx b/packages/client/src/components/lorebooks/LorebookFormFields.tsx index 4453bdc78..b1c89bef8 100644 --- a/packages/client/src/components/lorebooks/LorebookFormFields.tsx +++ b/packages/client/src/components/lorebooks/LorebookFormFields.tsx @@ -4,10 +4,11 @@ // and LorebookEntryRow (the per-entry inline drawer). // Extracted from LorebookEditor.tsx so styling stays consistent. // ────────────────────────────────────────────── -import { useEffect, useRef, useState, type KeyboardEvent as ReactKeyboardEvent } from "react"; -import { FileText, Maximize2, ToggleLeft, ToggleRight, X } from "lucide-react"; +import { useCallback, useEffect, useRef, useState, type KeyboardEvent as ReactKeyboardEvent } from "react"; +import { FileText, Maximize2, Sparkles, ToggleLeft, ToggleRight, X } from "lucide-react"; import { cn } from "../../lib/utils"; import { HelpTooltip } from "../ui/HelpTooltip"; +import { MagicRewritePanel } from "../ui/MagicRewritePanel"; export function FieldGroup({ label, @@ -233,6 +234,8 @@ export function ExpandedContentModal({ placeholder?: string; }) { const [local, setLocal] = useState(value); + const [magicRewriteMode, setMagicRewriteMode] = useState(false); + const [magicRewriteResult, setMagicRewriteResult] = useState(""); const textareaRef = useRef(null); useEffect(() => { @@ -241,7 +244,7 @@ export function ExpandedContentModal({ useEffect(() => { const handler = (e: KeyboardEvent) => { - if (e.key === "Escape") { + if (e.key === "Escape" && !magicRewriteMode) { onChange(local); onCommit?.(); onClose(); @@ -249,7 +252,7 @@ export function ExpandedContentModal({ }; document.addEventListener("keydown", handler); return () => document.removeEventListener("keydown", handler); - }, [onClose, onChange, onCommit, local]); + }, [onClose, onChange, onCommit, local, magicRewriteMode]); const handleClose = () => { onChange(local); @@ -257,36 +260,87 @@ export function ExpandedContentModal({ onClose(); }; + const handleMagicRewriteBack = () => { + setMagicRewriteMode(false); + setMagicRewriteResult(""); + }; + + const handleMagicRewriteApply = () => { + if (!magicRewriteResult) return; + setLocal(magicRewriteResult); + setMagicRewriteMode(false); + setMagicRewriteResult(""); + window.setTimeout(() => textareaRef.current?.focus(), 100); + }; + + const handleMagicRewriteResultChange = useCallback((next: string) => { + setMagicRewriteResult(next); + }, []); + return (
-
+
-

{title}

- +

{magicRewriteMode ? "✨ Magic Rewrite" : title}

+
+ +
-