One chat card, two modes: assistant and mesh, with a purple unread badge on the switch

Mesh is a mode rather than an AI profile — it has no model, tokens, reasoning or sources, so making it a profile would branch every profile-aware path on the one that has no model.
This commit is contained in:
Gmer4Lfe
2026-08-17 17:03:35 -04:00
parent d88fe381db
commit eab5cc911c
10 changed files with 371 additions and 293 deletions
+23 -1
View File
@@ -74,6 +74,9 @@
// so relying on something else having loaded the registry first works on the AI tab and fatals
// on the dashboard.
require_once __DIR__ . '/ai_profiles.php';
// The mesh pane the chat card can switch to. Required here rather than by each page, so a page
// that mounts a chat gets the option without having to know the store exists.
require_once __DIR__ . '/node_chat.php';
// The conversation store, on its own, with no styling and no chat widget attached.
//
@@ -2400,7 +2403,21 @@ function vv_ai_chat_markup(string $prefix, array $o = []): void {
<div class="vv-ai-head">
<span class="vv-ai-head-t">
<?php if (!empty($o['icon'])): ?><span class="vv-ico"><?= $o['icon'] ?></span><?php endif; ?>
<?= htmlspecialchars($o['title'] ?? 'Assistant') ?>
<span id="<?= $p ?>-title"><?= htmlspecialchars($o['title'] ?? 'Assistant') ?></span>
<?php if (!empty($o['mesh'])): ?>
<!-- The badge is the whole reason a toggle is acceptable here. Behind a switch, an arriving
message is invisible until somebody happens to flip it — and the messages this carries
are the ones you most need to not miss ("mine is going down for a week"). Purple because
nothing else on these pages is, so it reads as new rather than as another warning. -->
<button type="button" id="<?= $p ?>-mode" class="vv-ai-btn ghost"
onclick="vvNcMode()" title="Switch between the assistant and the mesh"
style="margin-left:8px;font-size:10px;padding:2px 8px;">
<span id="<?= $p ?>-mode-l">Mesh</span>
<span id="vv-nc-badge" hidden
style="margin-left:5px;background:#7c4dff;color:#fff;border-radius:8px;
padding:0 6px;font-size:9px;font-weight:700;">✉ 0</span>
</button>
<?php endif; ?>
</span>
<!-- Centred by giving the title and the right-hand group equal flex, not by margins — the
@@ -2460,6 +2477,9 @@ function vv_ai_chat_markup(string $prefix, array $o = []): void {
<!-- Positioned wrapper so the jump pill can sit over the transcript's bottom edge without
being clipped by its overflow, and without taking a row of its own when hidden. -->
<!-- Two panes, one card. The mesh pane is a sibling of this one rather than a second card, so
switching what the card is does not give the page a second header to look at. -->
<div id="<?= $p ?>-pane-ai">
<div class="vv-ai-chat-wrap">
<div class="vv-ai-chat" id="<?= $p ?>-chat"<?= $style ?>>
<div class="vv-ai-empty"><?= htmlspecialchars($empty) ?></div>
@@ -2529,6 +2549,8 @@ function vv_ai_chat_markup(string $prefix, array $o = []): void {
</div>
</div>
</div>
</div><?php /* close -pane-ai */ ?>
<?php if (!empty($o['mesh']) && function_exists('vv_nc_pane_markup')) vv_nc_pane_markup($p, !empty($o['meshDefault'])); ?>
</div>
<?php
}