feat: STT transcripts, model catalog+fuzzy resolve, UI audio player & auto-refresh
Core: - ModelCatalog: periodic background sync of provider models + fuzzy resolve. Misspelled model ids map to the nearest match (cheapest on ties); no match raises ModelResolutionError with cheapest-first suggestions for the agent. mcp-server: - nexus_stt now writes the transcript to a Markdown file in the media dir so it appears in the gallery and is readable in the modal. - media handler resolves model via catalog before generating; returns a note when substituting, or a BAD_REQUEST with available models when nothing fits. - context wires a ModelCatalog per media provider with auto-sync. admin: - /media serves correct Content-Type (incl. text/markdown for transcripts). - Gallery: audio play button on cards, dedicated audio player in modal, text/transcript tiles that fetch and render the .md in the modal. - Header: auto-refresh toggle (5/10/30s) that refreshes the active tab without a full page reload; pauses while a modal is open.
This commit is contained in:
@@ -85,6 +85,26 @@
|
||||
.modal-body img, .modal-body video { max-width: 88vw; max-height: 72vh; display: block; margin: 0 auto; }
|
||||
.modal-body audio { width: 60vw; max-width: 600px; }
|
||||
.kv { color: var(--muted); font-size: 12px; margin-top: 10px; word-break: break-all; }
|
||||
/* Auto-refresh control */
|
||||
.autorefresh { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
|
||||
.autorefresh select { width: auto; padding: 4px 6px; }
|
||||
.autorefresh input[type="checkbox"] { width: auto; }
|
||||
/* Audio card thumb + play button */
|
||||
.audio-thumb, .text-thumb { height: 150px; display: flex; align-items: center; justify-content: center;
|
||||
cursor: pointer; background: linear-gradient(135deg, var(--panel2), var(--panel)); }
|
||||
.text-thumb.err { background: rgba(242,109,109,.08); }
|
||||
.play-btn { width: 56px; height: 56px; border-radius: 50%; border: none; cursor: pointer;
|
||||
background: var(--accent); color: #fff; font-size: 20px; line-height: 1;
|
||||
box-shadow: 0 6px 18px var(--shadow); transition: transform .1s; }
|
||||
.play-btn:hover { transform: scale(1.08); }
|
||||
.doc-icon { font-size: 42px; opacity: .8; }
|
||||
/* Modal audio player */
|
||||
.audio-player { display: flex; flex-direction: column; align-items: center; gap: 16px; padding: 20px; }
|
||||
.audio-visual { font-size: 64px; }
|
||||
/* Transcript / doc view */
|
||||
.doc-view { white-space: pre-wrap; word-break: break-word; font: 13px/1.6 ui-monospace, SFMono-Regular, Menlo, monospace;
|
||||
background: var(--panel2); border: 1px solid var(--line); border-radius: 8px; padding: 16px;
|
||||
max-width: 80vw; max-height: 70vh; overflow: auto; text-align: left; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -92,6 +112,14 @@
|
||||
<h1>NexusAI Admin</h1>
|
||||
<span class="badge" id="cryptoBadge"></span>
|
||||
<span class="spacer"></span>
|
||||
<label class="autorefresh" title="Автообновление активной вкладки">
|
||||
<input type="checkbox" id="autoRefresh" /> Авто-обновление
|
||||
<select id="autoRefreshInterval">
|
||||
<option value="5000">5с</option>
|
||||
<option value="10000" selected>10с</option>
|
||||
<option value="30000">30с</option>
|
||||
</select>
|
||||
</label>
|
||||
<button id="themeToggle" title="Переключить тему">🌙 Тёмная</button>
|
||||
</header>
|
||||
<nav>
|
||||
@@ -141,6 +169,7 @@
|
||||
<option value="music">music</option>
|
||||
<option value="video">video</option>
|
||||
<option value="stt">stt</option>
|
||||
<option value="vision">vision</option>
|
||||
<option value="search">search</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user