Spaces:
Sleeping
Sleeping
Download dashboard/features/observability/controller.js from JuanCS-Dev/twitch-byte-bot: direct link, hf CLI and curl.
- Browser
- Download file 11.4 kB
-
https://huggingface.co/spaces/JuanCS-Dev/twitch-byte-bot/resolve/main/dashboard/features/observability/controller.js
- Command line
-
hf download hf://spaces/JuanCS-Dev/twitch-byte-bot/dashboard/features/observability/controller.js
-
curl -L -o controller.js https://huggingface.co/spaces/JuanCS-Dev/twitch-byte-bot/resolve/main/dashboard/features/observability/controller.js
11.4 kB
| import { | |
| getChannelContextSnapshot, | |
| getObservabilityHistorySnapshot, | |
| getPostStreamReportSnapshot, | |
| getSemanticMemorySnapshot, | |
| getObservabilitySnapshot, | |
| getSentimentScoresSnapshot, | |
| upsertSemanticMemoryEntry, | |
| getRevenueConversionsSnapshot, | |
| postRevenueConversion, | |
| } from "./api.js"; | |
| import { | |
| renderChannelContextSnapshot, | |
| renderObservabilityHistorySnapshot, | |
| renderPostStreamReportSnapshot, | |
| renderSemanticMemorySnapshot, | |
| renderObservabilitySnapshot, | |
| setConnectionState, | |
| renderRevenueConversionsSnapshot, | |
| } from "./view.js"; | |
| import { applyChannelControlCapability } from "../channel-control/view.js"; | |
| import { renderControlPlaneCapabilities } from "../control-plane/view.js"; | |
| import { renderAutonomyRuntime } from "../autonomy/view.js"; | |
| const OBSERVABILITY_INTERVAL_MS = 10000; | |
| const OBSERVABILITY_TIMEOUT_MS = 8000; | |
| const OBSERVABILITY_HISTORY_LIMIT = 24; | |
| const OBSERVABILITY_COMPARE_LIMIT = 6; | |
| const SEMANTIC_MEMORY_LIMIT = 8; | |
| const SEMANTIC_MEMORY_SEARCH_LIMIT = 60; | |
| function normalizeSemanticMinSimilarity(value) { | |
| const raw = String(value ?? "").trim(); | |
| if (!raw) return ""; | |
| const parsed = Number(raw); | |
| if (!Number.isFinite(parsed)) return ""; | |
| const clamped = Math.max(-1, Math.min(1, parsed)); | |
| return String(Number(clamped.toFixed(3))); | |
| } | |
| export function createObservabilityController({ | |
| obsEls, | |
| ctrlEls, | |
| cpEls, | |
| autEls, | |
| }) { | |
| let isPolling = false; | |
| let timerId = 0; | |
| let selectedChannel = "default"; | |
| let semanticMemoryQuery = ""; | |
| let semanticMemoryMinSimilarity = ""; | |
| let semanticMemoryForceFallback = false; | |
| function syncSemanticMemorySearchTuning() { | |
| if (!obsEls) return; | |
| semanticMemoryMinSimilarity = normalizeSemanticMinSimilarity( | |
| obsEls.intSemanticMemoryMinSimilarityInput?.value, | |
| ); | |
| semanticMemoryForceFallback = Boolean( | |
| obsEls.intSemanticMemoryForceFallbackToggle?.checked, | |
| ); | |
| } | |
| function applyRuntimeCapabilities(capabilities = {}, mode = "") { | |
| if (ctrlEls) { | |
| applyChannelControlCapability( | |
| ctrlEls, | |
| capabilities?.channel_control || {}, | |
| ); | |
| } | |
| if (cpEls) { | |
| renderControlPlaneCapabilities(cpEls, capabilities || {}, mode || ""); | |
| } | |
| } | |
| async function fetchAndRenderObservability() { | |
| if (!obsEls || isPolling) return; | |
| syncSemanticMemorySearchTuning(); | |
| isPolling = true; | |
| setConnectionState("pending", obsEls); | |
| try { | |
| const sentimentPromise = getSentimentScoresSnapshot( | |
| selectedChannel, | |
| OBSERVABILITY_TIMEOUT_MS, | |
| ).catch((_error) => null); | |
| const [ | |
| data, | |
| channelData, | |
| historyData, | |
| sentimentData, | |
| postStreamData, | |
| semanticMemoryData, | |
| revenueData, | |
| ] = await Promise.all([ | |
| getObservabilitySnapshot(selectedChannel, OBSERVABILITY_TIMEOUT_MS), | |
| getChannelContextSnapshot(selectedChannel, OBSERVABILITY_TIMEOUT_MS), | |
| getObservabilityHistorySnapshot( | |
| selectedChannel, | |
| OBSERVABILITY_TIMEOUT_MS, | |
| OBSERVABILITY_HISTORY_LIMIT, | |
| OBSERVABILITY_COMPARE_LIMIT, | |
| ), | |
| sentimentPromise, | |
| getPostStreamReportSnapshot( | |
| selectedChannel, | |
| OBSERVABILITY_TIMEOUT_MS, | |
| ).catch((_error) => null), | |
| getSemanticMemorySnapshot( | |
| selectedChannel, | |
| OBSERVABILITY_TIMEOUT_MS, | |
| semanticMemoryQuery, | |
| SEMANTIC_MEMORY_LIMIT, | |
| SEMANTIC_MEMORY_SEARCH_LIMIT, | |
| semanticMemoryMinSimilarity, | |
| semanticMemoryForceFallback, | |
| ).catch((_error) => null), | |
| getRevenueConversionsSnapshot( | |
| selectedChannel, | |
| OBSERVABILITY_TIMEOUT_MS, | |
| ).catch((_error) => null), | |
| ]); | |
| renderObservabilitySnapshot(data, obsEls, sentimentData); | |
| renderChannelContextSnapshot(channelData, obsEls); | |
| renderObservabilityHistorySnapshot(historyData, obsEls); | |
| renderPostStreamReportSnapshot(postStreamData, obsEls); | |
| renderSemanticMemorySnapshot(semanticMemoryData, obsEls); | |
| renderRevenueConversionsSnapshot(revenueData, obsEls); | |
| setConnectionState("ok", obsEls); | |
| applyRuntimeCapabilities(data?.capabilities || {}, data?.bot?.mode || ""); | |
| renderAutonomyRuntime(data?.autonomy || {}, autEls); | |
| } catch (error) { | |
| console.error("Dashboard observability refresh error", error); | |
| setConnectionState("error", obsEls); | |
| } finally { | |
| isPolling = false; | |
| } | |
| } | |
| async function generatePostStreamReport() { | |
| if (!obsEls) return null; | |
| if (obsEls.intPostStreamGenerateBtn) { | |
| obsEls.intPostStreamGenerateBtn.disabled = true; | |
| } | |
| try { | |
| const payload = await getPostStreamReportSnapshot( | |
| selectedChannel, | |
| OBSERVABILITY_TIMEOUT_MS, | |
| true, | |
| ); | |
| renderPostStreamReportSnapshot(payload, obsEls); | |
| return payload; | |
| } catch (error) { | |
| console.error("Dashboard post-stream report generation error", error); | |
| return null; | |
| } finally { | |
| if (obsEls.intPostStreamGenerateBtn) { | |
| obsEls.intPostStreamGenerateBtn.disabled = false; | |
| } | |
| } | |
| } | |
| async function refreshSemanticMemory(query = "") { | |
| if (!obsEls) return null; | |
| syncSemanticMemorySearchTuning(); | |
| semanticMemoryQuery = String(query || "").trim(); | |
| try { | |
| const payload = await getSemanticMemorySnapshot( | |
| selectedChannel, | |
| OBSERVABILITY_TIMEOUT_MS, | |
| semanticMemoryQuery, | |
| SEMANTIC_MEMORY_LIMIT, | |
| SEMANTIC_MEMORY_SEARCH_LIMIT, | |
| semanticMemoryMinSimilarity, | |
| semanticMemoryForceFallback, | |
| ); | |
| renderSemanticMemorySnapshot(payload, obsEls); | |
| return payload; | |
| } catch (error) { | |
| console.error("Dashboard semantic memory refresh error", error); | |
| return null; | |
| } | |
| } | |
| async function saveSemanticMemoryEntry() { | |
| if (!obsEls) return null; | |
| const content = String( | |
| obsEls.intSemanticMemoryContentInput?.value || "", | |
| ).trim(); | |
| if (!content) return null; | |
| if (obsEls.intSemanticMemorySaveBtn) { | |
| obsEls.intSemanticMemorySaveBtn.disabled = true; | |
| } | |
| try { | |
| await upsertSemanticMemoryEntry( | |
| { | |
| channel_id: selectedChannel, | |
| content, | |
| memory_type: String( | |
| obsEls.intSemanticMemoryTypeInput?.value || "fact", | |
| ) | |
| .trim() | |
| .toLowerCase(), | |
| tags: String(obsEls.intSemanticMemoryTagsInput?.value || ""), | |
| }, | |
| OBSERVABILITY_TIMEOUT_MS, | |
| ); | |
| if (obsEls.intSemanticMemoryContentInput) { | |
| obsEls.intSemanticMemoryContentInput.value = ""; | |
| } | |
| syncSemanticMemorySearchTuning(); | |
| const queryFromInput = String( | |
| obsEls.intSemanticMemoryQueryInput?.value || "", | |
| ).trim(); | |
| await refreshSemanticMemory(queryFromInput); | |
| return true; | |
| } catch (error) { | |
| console.error("Dashboard semantic memory save error", error); | |
| return null; | |
| } finally { | |
| if (obsEls.intSemanticMemorySaveBtn) { | |
| obsEls.intSemanticMemorySaveBtn.disabled = false; | |
| } | |
| } | |
| } | |
| async function simulateRevenueConversion() { | |
| if (!obsEls || !obsEls.intRevenueSimulateBtn) return null; | |
| const btn = obsEls.intRevenueSimulateBtn; | |
| const eventType = obsEls.intRevenueEventType?.value || "sub"; | |
| const viewerLogin = String( | |
| obsEls.intRevenueViewerLogin?.value || "simulated_viewer", | |
| ).trim(); | |
| const rawValue = obsEls.intRevenueValue?.value || "0"; | |
| const revenueValue = Number(rawValue) || 0.0; | |
| btn.disabled = true; | |
| try { | |
| await postRevenueConversion( | |
| { | |
| channel_id: selectedChannel, | |
| event_type: eventType, | |
| viewer_login: viewerLogin, | |
| revenue_value: revenueValue, | |
| }, | |
| OBSERVABILITY_TIMEOUT_MS, | |
| ); | |
| if (obsEls.intRevenueViewerLogin) obsEls.intRevenueViewerLogin.value = ""; | |
| if (obsEls.intRevenueValue) obsEls.intRevenueValue.value = ""; | |
| const payload = await getRevenueConversionsSnapshot( | |
| selectedChannel, | |
| OBSERVABILITY_TIMEOUT_MS, | |
| ); | |
| renderRevenueConversionsSnapshot(payload, obsEls); | |
| return true; | |
| } catch (error) { | |
| console.error("Dashboard revenue simulation error", error); | |
| return null; | |
| } finally { | |
| btn.disabled = false; | |
| } | |
| } | |
| function bindObservabilityEvents() { | |
| if (!obsEls) return; | |
| if (obsEls.intPostStreamGenerateBtn) { | |
| obsEls.intPostStreamGenerateBtn.addEventListener( | |
| "click", | |
| async (event) => { | |
| event.preventDefault(); | |
| await generatePostStreamReport(); | |
| }, | |
| ); | |
| } | |
| if (obsEls.intSemanticMemorySearchBtn) { | |
| obsEls.intSemanticMemorySearchBtn.addEventListener( | |
| "click", | |
| async (event) => { | |
| event.preventDefault(); | |
| syncSemanticMemorySearchTuning(); | |
| const query = String( | |
| obsEls.intSemanticMemoryQueryInput?.value || "", | |
| ).trim(); | |
| await refreshSemanticMemory(query); | |
| }, | |
| ); | |
| } | |
| if (obsEls.intSemanticMemorySaveBtn) { | |
| obsEls.intSemanticMemorySaveBtn.addEventListener( | |
| "click", | |
| async (event) => { | |
| event.preventDefault(); | |
| await saveSemanticMemoryEntry(); | |
| }, | |
| ); | |
| } | |
| if (obsEls.intSemanticMemoryMinSimilarityInput) { | |
| obsEls.intSemanticMemoryMinSimilarityInput.addEventListener( | |
| "change", | |
| async () => { | |
| syncSemanticMemorySearchTuning(); | |
| const query = String( | |
| obsEls.intSemanticMemoryQueryInput?.value || "", | |
| ).trim(); | |
| await refreshSemanticMemory(query); | |
| }, | |
| ); | |
| } | |
| if (obsEls.intSemanticMemoryForceFallbackToggle) { | |
| obsEls.intSemanticMemoryForceFallbackToggle.addEventListener( | |
| "change", | |
| async () => { | |
| syncSemanticMemorySearchTuning(); | |
| const query = String( | |
| obsEls.intSemanticMemoryQueryInput?.value || "", | |
| ).trim(); | |
| await refreshSemanticMemory(query); | |
| }, | |
| ); | |
| } | |
| if (obsEls.intRevenueSimulateBtn) { | |
| obsEls.intRevenueSimulateBtn.addEventListener("click", async (event) => { | |
| event.preventDefault(); | |
| await simulateRevenueConversion(); | |
| }); | |
| } | |
| } | |
| function scheduleObservabilityPolling() { | |
| if (timerId) { | |
| window.clearTimeout(timerId); | |
| } | |
| timerId = window.setTimeout(async () => { | |
| await fetchAndRenderObservability(); | |
| scheduleObservabilityPolling(); | |
| }, OBSERVABILITY_INTERVAL_MS); | |
| } | |
| return { | |
| applyRuntimeCapabilities, | |
| fetchAndRenderObservability, | |
| // O2b: render the health metrics from the live ops snapshot. | |
| // snap.observability === /api/observability and snap.sentiment === | |
| // /api/sentiment/scores (both verified) — the same args fetchAndRender uses. | |
| renderObservabilityFromSnapshot(snap) { | |
| if (obsEls && snap) { | |
| renderObservabilitySnapshot(snap.observability || {}, obsEls, snap.sentiment || {}); | |
| setConnectionState("ok", obsEls); | |
| } | |
| }, | |
| generatePostStreamReport, | |
| refreshSemanticMemory, | |
| saveSemanticMemoryEntry, | |
| bindObservabilityEvents, | |
| setSelectedChannel(channelId) { | |
| selectedChannel = | |
| String(channelId || "") | |
| .trim() | |
| .toLowerCase() || "default"; | |
| }, | |
| scheduleObservabilityPolling, | |
| }; | |
| } | |