@callmedayz/ai-prompt-toolkit
Version:
Professional AI prompt engineering toolkit with advanced template features, real-time dashboards, conditional logic, template inheritance, live monitoring, OpenRouter integration, and 310+ model support
488 lines • 16.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RealTimeDashboard = void 0;
/**
* Real-time Dashboard System for Prompt Performance Monitoring
* Provides live dashboards, real-time metrics, and monitoring capabilities
*/
class RealTimeDashboard {
constructor(analytics) {
this.layouts = new Map();
this.metrics = new Map();
this.events = [];
this.subscribers = new Map();
this.refreshIntervals = new Map();
this.isMonitoring = false;
this.analytics = analytics;
this.initializeDefaultLayouts();
}
/**
* Start real-time monitoring
*/
startMonitoring() {
if (this.isMonitoring)
return;
this.isMonitoring = true;
// Start monitoring for all active layouts
this.layouts.forEach((layout, layoutId) => {
if (layout.autoRefresh) {
this.startLayoutRefresh(layoutId);
}
});
console.log('🔴 Real-time dashboard monitoring started');
}
/**
* Stop real-time monitoring
*/
stopMonitoring() {
if (!this.isMonitoring)
return;
this.isMonitoring = false;
// Clear all refresh intervals
this.refreshIntervals.forEach(interval => clearInterval(interval));
this.refreshIntervals.clear();
console.log('⏹️ Real-time dashboard monitoring stopped');
}
/**
* Create a new dashboard layout
*/
createLayout(layout) {
const id = `layout_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
const fullLayout = { id, ...layout };
this.layouts.set(id, fullLayout);
if (fullLayout.autoRefresh && this.isMonitoring) {
this.startLayoutRefresh(id);
}
return id;
}
/**
* Get dashboard layout by ID
*/
getLayout(layoutId) {
return this.layouts.get(layoutId);
}
/**
* Update dashboard layout
*/
updateLayout(layoutId, updates) {
const layout = this.layouts.get(layoutId);
if (!layout)
throw new Error(`Layout ${layoutId} not found`);
const updatedLayout = { ...layout, ...updates };
this.layouts.set(layoutId, updatedLayout);
// Restart refresh if needed
if (this.isMonitoring) {
this.stopLayoutRefresh(layoutId);
if (updatedLayout.autoRefresh) {
this.startLayoutRefresh(layoutId);
}
}
this.notifySubscribers(`layout:${layoutId}`, updatedLayout);
}
/**
* Get real-time metrics for a widget
*/
getWidgetData(widget, filters = []) {
switch (widget.type) {
case 'metric':
return this.getMetricData(widget, filters);
case 'chart':
return this.getChartData(widget, filters);
case 'table':
return this.getTableData(widget, filters);
case 'alert':
return this.getAlertData(widget, filters);
case 'trend':
return this.getTrendData(widget, filters);
default:
return null;
}
}
/**
* Subscribe to real-time updates
*/
subscribe(channel, callback) {
if (!this.subscribers.has(channel)) {
this.subscribers.set(channel, []);
}
this.subscribers.get(channel).push(callback);
// Return unsubscribe function
return () => {
const callbacks = this.subscribers.get(channel);
if (callbacks) {
const index = callbacks.indexOf(callback);
if (index > -1) {
callbacks.splice(index, 1);
}
}
};
}
/**
* Add a live monitoring event
*/
addEvent(event) {
const fullEvent = {
id: `event_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
timestamp: new Date(),
...event
};
this.events.unshift(fullEvent);
// Keep only last 1000 events
if (this.events.length > 1000) {
this.events = this.events.slice(0, 1000);
}
this.notifySubscribers('events', fullEvent);
// Trigger alerts if critical
if (fullEvent.severity === 'critical') {
this.notifySubscribers('alerts', fullEvent);
}
}
/**
* Get recent events
*/
getEvents(limit = 50, severity) {
let filteredEvents = this.events;
if (severity) {
filteredEvents = this.events.filter(event => event.severity === severity);
}
return filteredEvents.slice(0, limit);
}
/**
* Update a real-time metric
*/
updateMetric(metricId, value, metadata) {
const existing = this.metrics.get(metricId);
const previousValue = existing?.value;
let change = 0;
let changePercent = 0;
let trend = 'stable';
if (previousValue !== undefined) {
change = value - previousValue;
changePercent = previousValue !== 0 ? (change / previousValue) * 100 : 0;
if (Math.abs(changePercent) < 1) {
trend = 'stable';
}
else {
trend = change > 0 ? 'up' : 'down';
}
}
const metric = {
id: metricId,
name: existing?.name || metricId,
value,
previousValue,
change,
changePercent,
trend,
status: this.calculateMetricStatus(metricId, value),
timestamp: new Date(),
unit: existing?.unit,
format: existing?.format,
...metadata
};
this.metrics.set(metricId, metric);
this.notifySubscribers(`metric:${metricId}`, metric);
}
/**
* Get all available layouts
*/
getLayouts() {
return Array.from(this.layouts.values());
}
/**
* Export dashboard configuration
*/
exportDashboard(layoutId) {
const data = layoutId
? { layout: this.layouts.get(layoutId) }
: { layouts: Array.from(this.layouts.values()) };
return JSON.stringify(data, null, 2);
}
/**
* Import dashboard configuration
*/
importDashboard(configJson) {
const config = JSON.parse(configJson);
if (config.layout) {
this.layouts.set(config.layout.id, config.layout);
}
else if (config.layouts) {
config.layouts.forEach((layout) => {
this.layouts.set(layout.id, layout);
});
}
}
/**
* Initialize default dashboard layouts
*/
initializeDefaultLayouts() {
// Performance Overview Dashboard
const performanceLayout = {
id: 'performance_overview',
name: 'Performance Overview',
description: 'Real-time overview of prompt performance metrics',
autoRefresh: true,
refreshInterval: 30, // 30 seconds
filters: [
{
id: 'timeRange',
type: 'timeRange',
label: 'Time Range',
value: '1h',
options: ['15m', '1h', '6h', '24h', '7d']
}
],
widgets: [
{
id: 'success_rate',
type: 'metric',
title: 'Success Rate',
position: { x: 0, y: 0, width: 3, height: 2 },
dataSource: 'analytics',
config: { metric: 'successRate', format: 'percentage' }
},
{
id: 'avg_response_time',
type: 'metric',
title: 'Avg Response Time',
position: { x: 3, y: 0, width: 3, height: 2 },
dataSource: 'analytics',
config: { metric: 'averageResponseTime', format: 'duration', unit: 'ms' }
},
{
id: 'total_executions',
type: 'metric',
title: 'Total Executions',
position: { x: 6, y: 0, width: 3, height: 2 },
dataSource: 'analytics',
config: { metric: 'totalExecutions', format: 'number' }
},
{
id: 'avg_cost',
type: 'metric',
title: 'Avg Cost',
position: { x: 9, y: 0, width: 3, height: 2 },
dataSource: 'analytics',
config: { metric: 'averageCost', format: 'currency' }
},
{
id: 'response_time_chart',
type: 'chart',
title: 'Response Time Trend',
position: { x: 0, y: 2, width: 6, height: 4 },
dataSource: 'analytics',
config: {
chartType: 'line',
metric: 'response_time',
timeWindow: '1h'
}
},
{
id: 'success_rate_chart',
type: 'chart',
title: 'Success Rate Trend',
position: { x: 6, y: 2, width: 6, height: 4 },
dataSource: 'analytics',
config: {
chartType: 'line',
metric: 'success',
timeWindow: '1h'
}
},
{
id: 'recent_alerts',
type: 'alert',
title: 'Recent Alerts',
position: { x: 0, y: 6, width: 12, height: 3 },
dataSource: 'events',
config: {
maxItems: 10,
severityFilter: ['medium', 'high', 'critical']
}
}
]
};
this.layouts.set(performanceLayout.id, performanceLayout);
// Cost Analysis Dashboard
const costLayout = {
id: 'cost_analysis',
name: 'Cost Analysis',
description: 'Monitor and analyze prompt execution costs',
autoRefresh: true,
refreshInterval: 60, // 1 minute
filters: [
{
id: 'timeRange',
type: 'timeRange',
label: 'Time Range',
value: '24h',
options: ['1h', '6h', '24h', '7d', '30d']
},
{
id: 'model',
type: 'model',
label: 'Model',
value: 'all',
options: ['all', 'gpt-4', 'gpt-3.5-turbo', 'claude-3']
}
],
widgets: [
{
id: 'total_cost',
type: 'metric',
title: 'Total Cost',
position: { x: 0, y: 0, width: 4, height: 2 },
dataSource: 'analytics',
config: { metric: 'totalCost', format: 'currency' }
},
{
id: 'cost_per_execution',
type: 'metric',
title: 'Cost per Execution',
position: { x: 4, y: 0, width: 4, height: 2 },
dataSource: 'analytics',
config: { metric: 'averageCost', format: 'currency' }
},
{
id: 'cost_trend',
type: 'trend',
title: 'Cost Trend',
position: { x: 8, y: 0, width: 4, height: 2 },
dataSource: 'analytics',
config: { metric: 'cost', period: '24h' }
}
]
};
this.layouts.set(costLayout.id, costLayout);
}
/**
* Start refresh interval for a layout
*/
startLayoutRefresh(layoutId) {
const layout = this.layouts.get(layoutId);
if (!layout)
return;
const interval = setInterval(() => {
this.refreshLayout(layoutId);
}, layout.refreshInterval * 1000);
this.refreshIntervals.set(layoutId, interval);
}
/**
* Stop refresh interval for a layout
*/
stopLayoutRefresh(layoutId) {
const interval = this.refreshIntervals.get(layoutId);
if (interval) {
clearInterval(interval);
this.refreshIntervals.delete(layoutId);
}
}
/**
* Refresh data for a layout
*/
refreshLayout(layoutId) {
const layout = this.layouts.get(layoutId);
if (!layout)
return;
// Update metrics for each widget
layout.widgets.forEach(widget => {
const data = this.getWidgetData(widget, layout.filters);
this.notifySubscribers(`widget:${widget.id}`, data);
});
this.notifySubscribers(`layout:${layoutId}:refresh`, { layoutId, timestamp: new Date() });
}
/**
* Get metric data for a widget
*/
getMetricData(widget, filters) {
// Implementation would fetch real data from analytics
// For now, return mock data structure
return {
value: Math.random() * 100,
change: (Math.random() - 0.5) * 10,
trend: Math.random() > 0.5 ? 'up' : 'down',
status: Math.random() > 0.7 ? 'good' : Math.random() > 0.3 ? 'warning' : 'critical'
};
}
/**
* Get chart data for a widget
*/
getChartData(widget, filters) {
// Implementation would fetch time-series data from analytics
const points = [];
const now = Date.now();
for (let i = 0; i < 24; i++) {
points.push({
timestamp: new Date(now - (23 - i) * 60 * 60 * 1000),
value: Math.random() * 100
});
}
return { points };
}
/**
* Get table data for a widget
*/
getTableData(widget, filters) {
// Implementation would fetch tabular data from analytics
return {
headers: ['Prompt Version', 'Success Rate', 'Avg Response Time', 'Cost'],
rows: [
['v1.0', '95%', '1.2s', '$0.003'],
['v1.1', '97%', '1.1s', '$0.004'],
['v2.0', '93%', '1.5s', '$0.002']
]
};
}
/**
* Get alert data for a widget
*/
getAlertData(widget, filters) {
const severityFilter = widget.config.severityFilter || [];
const maxItems = widget.config.maxItems || 10;
return this.getEvents(maxItems).filter(event => severityFilter.length === 0 || severityFilter.includes(event.severity));
}
/**
* Get trend data for a widget
*/
getTrendData(widget, filters) {
// Implementation would calculate trends from analytics data
return {
current: Math.random() * 100,
previous: Math.random() * 100,
change: (Math.random() - 0.5) * 20,
trend: Math.random() > 0.5 ? 'improving' : 'degrading'
};
}
/**
* Calculate metric status based on thresholds
*/
calculateMetricStatus(metricId, value) {
// This would use configurable thresholds
// For now, use simple logic
if (metricId.includes('success') || metricId.includes('rate')) {
return value > 90 ? 'good' : value > 70 ? 'warning' : 'critical';
}
else if (metricId.includes('time') || metricId.includes('cost')) {
return value < 1000 ? 'good' : value < 3000 ? 'warning' : 'critical';
}
return 'good';
}
/**
* Notify subscribers of updates
*/
notifySubscribers(channel, data) {
const callbacks = this.subscribers.get(channel);
if (callbacks) {
callbacks.forEach(callback => {
try {
callback(data);
}
catch (error) {
console.error(`Error in subscriber callback for ${channel}:`, error);
}
});
}
}
}
exports.RealTimeDashboard = RealTimeDashboard;
//# sourceMappingURL=real-time-dashboard.js.map