mirror of
https://github.com/ruvnet/RuView
synced 2026-08-07 20:01:43 +00:00
feat: vendor midstream and sublinear-time-solver libraries
Add ruvnet/midstream (AIMDS real-time inference) and ruvnet/sublinear-time-solver (sublinear optimization algorithms) as vendored dependencies under vendor/. Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
/**
|
||||
* Example: Agentic Flow Proxy Integration
|
||||
*
|
||||
* Demonstrates using OpenAI Realtime API through agentic-flow proxy
|
||||
* with workflow orchestration and MidStream analysis
|
||||
*/
|
||||
|
||||
import { AgenticFlowProxyClient, OpenAIRealtimeClient } from '../src/openai-realtime.js';
|
||||
import * as dotenv from 'dotenv';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
async function main() {
|
||||
console.log('🔄 Agentic Flow Proxy + OpenAI Realtime + MidStream');
|
||||
console.log('═══════════════════════════════════════════════════\n');
|
||||
|
||||
// Create agentic-flow proxy client
|
||||
const proxyClient = new AgenticFlowProxyClient({
|
||||
baseUrl: process.env.AGENTIC_FLOW_PROXY_URL || 'https://api.agenticflow.com/v1',
|
||||
apiKey: process.env.AGENTIC_FLOW_API_KEY!,
|
||||
openAiApiKey: process.env.OPENAI_API_KEY!,
|
||||
});
|
||||
|
||||
console.log('✓ Agentic Flow Proxy client created');
|
||||
|
||||
// Create realtime session through proxy
|
||||
const realtimeClient = await proxyClient.createRealtimeSession({
|
||||
apiKey: process.env.OPENAI_API_KEY!,
|
||||
model: process.env.OPENAI_REALTIME_MODEL,
|
||||
voice: 'nova',
|
||||
temperature: 0.7,
|
||||
});
|
||||
|
||||
console.log('✓ Realtime session created through proxy\n');
|
||||
|
||||
// Set up event listeners
|
||||
realtimeClient.on('session.created', (session) => {
|
||||
console.log('📡 Session ID:', session.id);
|
||||
|
||||
// Configure session
|
||||
realtimeClient.updateSession({
|
||||
modalities: ['text'],
|
||||
instructions: `You are an AI assistant integrated with agentic-flow for workflow orchestration.
|
||||
You can analyze conversations, detect patterns, and coordinate multi-agent workflows.`,
|
||||
temperature: 0.7,
|
||||
});
|
||||
});
|
||||
|
||||
realtimeClient.on('response.text.delta', (delta) => {
|
||||
process.stdout.write(delta);
|
||||
});
|
||||
|
||||
realtimeClient.on('response.done', () => {
|
||||
console.log('\n');
|
||||
});
|
||||
|
||||
realtimeClient.on('midstream.analysis', (status) => {
|
||||
console.log('🧠 MidStream:', {
|
||||
messages: status.conversationHistorySize,
|
||||
avgReward: status.averageReward.toFixed(2),
|
||||
});
|
||||
});
|
||||
|
||||
try {
|
||||
// Scenario 1: Simple conversation through proxy
|
||||
console.log('💬 Scenario 1: Proxied Conversation\n');
|
||||
console.log('User: Hello! I need help analyzing customer support patterns.\n');
|
||||
|
||||
realtimeClient.sendText('Hello! I need help analyzing customer support patterns.');
|
||||
|
||||
await new Promise(resolve => {
|
||||
realtimeClient.once('response.done', resolve);
|
||||
});
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
// Scenario 2: Pattern analysis
|
||||
console.log('\nUser: Can you detect patterns in this conversation flow?\n');
|
||||
|
||||
realtimeClient.sendText(`Can you analyze this conversation pattern:
|
||||
1. Customer: "I have a problem"
|
||||
2. Agent: "What's the issue?"
|
||||
3. Customer: "Can't login"
|
||||
4. Agent: "Let me help you reset your password"
|
||||
5. Customer: "Thank you, it works now"`);
|
||||
|
||||
await new Promise(resolve => {
|
||||
realtimeClient.once('response.done', resolve);
|
||||
});
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
// Get MidStream's pattern analysis
|
||||
console.log('\n📊 MidStream Pattern Analysis:');
|
||||
|
||||
const agent = realtimeClient.getAgent();
|
||||
const testSequence = [
|
||||
'problem_report',
|
||||
'info_request',
|
||||
'problem_description',
|
||||
'solution_offer',
|
||||
'gratitude',
|
||||
];
|
||||
|
||||
const commonPattern = ['problem_report', 'info_request', 'problem_description'];
|
||||
const positions = agent.detectPattern(testSequence, commonPattern);
|
||||
|
||||
console.log(' Pattern detected at positions:', positions);
|
||||
|
||||
// Compare with another sequence
|
||||
const similarSequence = [
|
||||
'problem_report',
|
||||
'info_request',
|
||||
'problem_description',
|
||||
'solution_offer',
|
||||
'confirmation',
|
||||
];
|
||||
|
||||
const similarity = agent.compareSequences(testSequence, similarSequence, 'dtw');
|
||||
console.log(' Similarity to variant pattern:', similarity.toFixed(3));
|
||||
|
||||
// Scenario 3: Workflow execution (if agentic-flow is configured)
|
||||
if (process.env.AGENTIC_FLOW_API_KEY) {
|
||||
console.log('\n🔄 Scenario 3: Workflow Orchestration\n');
|
||||
|
||||
try {
|
||||
// Example workflow execution
|
||||
// In production, you'd have pre-configured workflows in agentic-flow
|
||||
const workflowResult = await proxyClient.executeWorkflow('conversation-analyzer', {
|
||||
conversation: realtimeClient.getConversation(),
|
||||
analysisType: 'pattern_detection',
|
||||
});
|
||||
|
||||
console.log('Workflow result:', workflowResult);
|
||||
} catch (error: any) {
|
||||
console.log(' (Workflow not configured - this is expected in demo)');
|
||||
}
|
||||
}
|
||||
|
||||
// Final comprehensive analysis
|
||||
console.log('\n═══════════════════════════════════════');
|
||||
console.log('📈 Final Comprehensive Analysis');
|
||||
console.log('═══════════════════════════════════════\n');
|
||||
|
||||
const finalAnalysis = realtimeClient.getMidStreamAnalysis();
|
||||
console.log('MidStream Analysis:', JSON.stringify(finalAnalysis, null, 2));
|
||||
|
||||
const status = agent.getStatus();
|
||||
console.log('\nAgent Status:');
|
||||
console.log(' - Conversation size:', status.conversationHistorySize);
|
||||
console.log(' - Average reward:', status.averageReward.toFixed(3));
|
||||
console.log(' - Meta-learning level:', status.metaLearning.currentLevel);
|
||||
|
||||
// Behavior analysis
|
||||
if (status.rewardHistorySize > 5) {
|
||||
const behaviorAnalysis = agent.analyzeBehavior(
|
||||
Array(status.rewardHistorySize).fill(0.8)
|
||||
);
|
||||
|
||||
console.log('\nBehavior Analysis:');
|
||||
console.log(' - Is stable:', behaviorAnalysis.isStable);
|
||||
console.log(' - Is chaotic:', behaviorAnalysis.isChaotic);
|
||||
}
|
||||
|
||||
// Conversation insights
|
||||
const conversation = realtimeClient.getConversation();
|
||||
console.log('\nConversation Insights:');
|
||||
console.log(' - Total items:', conversation.length);
|
||||
console.log(' - User messages:', conversation.filter(i => i.role === 'user').length);
|
||||
console.log(' - Assistant messages:', conversation.filter(i => i.role === 'assistant').length);
|
||||
|
||||
// Cleanup
|
||||
realtimeClient.disconnect();
|
||||
console.log('\n✓ Session ended gracefully');
|
||||
process.exit(0);
|
||||
} catch (error) {
|
||||
console.error('\n❌ Error:', error);
|
||||
realtimeClient.disconnect();
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle graceful shutdown
|
||||
process.on('SIGINT', () => {
|
||||
console.log('\n\nShutting down...');
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,10 @@
|
||||
[
|
||||
"Hello! How can I help you today?",
|
||||
"I'm looking for information about the weather.",
|
||||
"I'd be happy to help with weather information. Which city are you interested in?",
|
||||
"Can you tell me about San Francisco?",
|
||||
"San Francisco typically has mild weather year-round. Would you like current conditions or a forecast?",
|
||||
"Current conditions please.",
|
||||
"The current temperature in San Francisco is 65°F with partly cloudy skies.",
|
||||
"Thank you! That's very helpful."
|
||||
]
|
||||
+429
@@ -0,0 +1,429 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* MidStream Dashboard Demo
|
||||
*
|
||||
* Comprehensive demonstration of MidStream capabilities:
|
||||
* - Real-time dashboard with WASM support
|
||||
* - Text/Audio/Video streaming introspection
|
||||
* - Temporal pattern analysis
|
||||
* - Attractor detection
|
||||
* - Meta-learning visualization
|
||||
*
|
||||
* Created by rUv
|
||||
*/
|
||||
|
||||
import { MidStreamDashboard } from '../src/dashboard.js';
|
||||
import { RestreamClient, StreamSimulator } from '../src/restream-integration.js';
|
||||
import { OpenAIRealtimeClient } from '../src/openai-realtime.js';
|
||||
import chalk from 'chalk';
|
||||
import * as dotenv from 'dotenv';
|
||||
|
||||
// Load environment variables
|
||||
dotenv.config();
|
||||
|
||||
// ============================================================================
|
||||
// Demo Configuration
|
||||
// ============================================================================
|
||||
|
||||
interface DemoConfig {
|
||||
mode: 'text' | 'audio' | 'video' | 'all';
|
||||
simulateStream: boolean;
|
||||
useOpenAI: boolean;
|
||||
duration: number; // seconds
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Demo Scenarios
|
||||
// ============================================================================
|
||||
|
||||
const DEMO_MESSAGES = [
|
||||
'Hello, I need help with my account',
|
||||
'I am having trouble logging in',
|
||||
'Can you reset my password?',
|
||||
'Thank you for your help',
|
||||
'I have another question about billing',
|
||||
'What are your pricing plans?',
|
||||
'Can I upgrade my subscription?',
|
||||
'How do I cancel my account?',
|
||||
'Is there a refund policy?',
|
||||
'Thanks for the information',
|
||||
];
|
||||
|
||||
// ============================================================================
|
||||
// Main Demo Class
|
||||
// ============================================================================
|
||||
|
||||
class MidStreamDemo {
|
||||
private dashboard: MidStreamDashboard;
|
||||
private restreamClient: RestreamClient | null = null;
|
||||
private streamSimulator: StreamSimulator | null = null;
|
||||
private realtimeClient: OpenAIRealtimeClient | null = null;
|
||||
private config: DemoConfig;
|
||||
private messageIndex: number = 0;
|
||||
|
||||
constructor(config: DemoConfig) {
|
||||
this.config = config;
|
||||
this.dashboard = new MidStreamDashboard();
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// Demo Modes
|
||||
// ==========================================================================
|
||||
|
||||
/**
|
||||
* Run text-only demo
|
||||
*/
|
||||
async runTextDemo(): Promise<void> {
|
||||
console.log(chalk.bold.cyan('\n🚀 Starting Text Streaming Demo\n'));
|
||||
|
||||
this.dashboard.start(100);
|
||||
|
||||
// Simulate incoming messages
|
||||
const messageInterval = setInterval(() => {
|
||||
if (this.messageIndex >= DEMO_MESSAGES.length) {
|
||||
this.messageIndex = 0;
|
||||
}
|
||||
|
||||
const message = DEMO_MESSAGES[this.messageIndex++];
|
||||
const tokens = Math.floor(message.split(' ').length * 1.3);
|
||||
|
||||
this.dashboard.processMessage(message, tokens);
|
||||
}, 2000);
|
||||
|
||||
// Run for configured duration
|
||||
await this.sleep(this.config.duration * 1000);
|
||||
|
||||
clearInterval(messageInterval);
|
||||
this.dashboard.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run audio streaming demo
|
||||
*/
|
||||
async runAudioDemo(): Promise<void> {
|
||||
console.log(chalk.bold.cyan('\n🎵 Starting Audio Streaming Demo\n'));
|
||||
|
||||
this.dashboard.start(100);
|
||||
|
||||
if (this.config.simulateStream) {
|
||||
this.streamSimulator = new StreamSimulator(30);
|
||||
|
||||
this.streamSimulator.start(
|
||||
() => {}, // Skip video frames
|
||||
(audio) => {
|
||||
this.dashboard.processStream('audio-stream-1', audio.data, 'audio');
|
||||
|
||||
// Simulate transcription every few chunks
|
||||
if (Math.random() < 0.3) {
|
||||
const message = DEMO_MESSAGES[this.messageIndex++ % DEMO_MESSAGES.length];
|
||||
this.dashboard.processMessage(message, 50);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Run for configured duration
|
||||
await this.sleep(this.config.duration * 1000);
|
||||
|
||||
if (this.streamSimulator) {
|
||||
this.streamSimulator.stop();
|
||||
}
|
||||
this.dashboard.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run video streaming demo
|
||||
*/
|
||||
async runVideoDemo(): Promise<void> {
|
||||
console.log(chalk.bold.cyan('\n📹 Starting Video Streaming Demo\n'));
|
||||
|
||||
this.dashboard.start(100);
|
||||
|
||||
if (this.config.simulateStream) {
|
||||
this.streamSimulator = new StreamSimulator(30);
|
||||
|
||||
this.streamSimulator.start(
|
||||
(frame) => {
|
||||
this.dashboard.processStream('video-stream-1', frame.data, 'video');
|
||||
|
||||
// Simulate object detection every 30 frames
|
||||
if (frame.frameNumber % 30 === 0) {
|
||||
const message = `Detected objects in frame ${frame.frameNumber}`;
|
||||
this.dashboard.processMessage(message, 20);
|
||||
}
|
||||
},
|
||||
(audio) => {
|
||||
this.dashboard.processStream('audio-stream-1', audio.data, 'audio');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Run for configured duration
|
||||
await this.sleep(this.config.duration * 1000);
|
||||
|
||||
if (this.streamSimulator) {
|
||||
this.streamSimulator.stop();
|
||||
}
|
||||
this.dashboard.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run comprehensive demo with all features
|
||||
*/
|
||||
async runFullDemo(): Promise<void> {
|
||||
console.log(chalk.bold.cyan('\n🌟 Starting Comprehensive MidStream Demo\n'));
|
||||
console.log(chalk.gray('Demonstrating all capabilities:\n'));
|
||||
console.log(chalk.yellow(' • Real-time text processing'));
|
||||
console.log(chalk.yellow(' • Audio stream introspection'));
|
||||
console.log(chalk.yellow(' • Video stream analysis'));
|
||||
console.log(chalk.yellow(' • Temporal pattern detection'));
|
||||
console.log(chalk.yellow(' • Attractor analysis'));
|
||||
console.log(chalk.yellow(' • Meta-learning'));
|
||||
console.log(chalk.gray('\nPress Ctrl+C to exit\n'));
|
||||
|
||||
await this.sleep(2000);
|
||||
|
||||
this.dashboard.start(100);
|
||||
|
||||
// Start stream simulator
|
||||
if (this.config.simulateStream) {
|
||||
this.streamSimulator = new StreamSimulator(30);
|
||||
|
||||
this.streamSimulator.start(
|
||||
(frame) => {
|
||||
this.dashboard.processStream('video-stream-1', frame.data, 'video');
|
||||
|
||||
// Simulate detections and analysis
|
||||
if (frame.frameNumber % 30 === 0) {
|
||||
const message = `Frame ${frame.frameNumber}: detected 2 objects`;
|
||||
this.dashboard.processMessage(message, 15);
|
||||
}
|
||||
},
|
||||
(audio) => {
|
||||
this.dashboard.processStream('audio-stream-1', audio.data, 'audio');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Simulate text messages
|
||||
const messageInterval = setInterval(() => {
|
||||
if (this.messageIndex >= DEMO_MESSAGES.length) {
|
||||
this.messageIndex = 0;
|
||||
}
|
||||
|
||||
const message = DEMO_MESSAGES[this.messageIndex++];
|
||||
const tokens = Math.floor(message.split(' ').length * 1.3);
|
||||
|
||||
this.dashboard.processMessage(message, tokens);
|
||||
}, 3000);
|
||||
|
||||
// Initialize Restream client if configured
|
||||
if (this.config.simulateStream) {
|
||||
this.restreamClient = new RestreamClient({
|
||||
frameRate: 30,
|
||||
resolution: '1920x1080',
|
||||
enableTranscription: true,
|
||||
enableObjectDetection: true,
|
||||
});
|
||||
|
||||
this.restreamClient.on('frame', (frame) => {
|
||||
// Process frame
|
||||
});
|
||||
|
||||
this.restreamClient.on('audio', (audio) => {
|
||||
// Process audio
|
||||
});
|
||||
|
||||
this.restreamClient.on('transcription', (text) => {
|
||||
this.dashboard.processMessage(`Transcription: ${text}`, 20);
|
||||
});
|
||||
}
|
||||
|
||||
// Run for configured duration
|
||||
await this.sleep(this.config.duration * 1000);
|
||||
|
||||
clearInterval(messageInterval);
|
||||
if (this.streamSimulator) {
|
||||
this.streamSimulator.stop();
|
||||
}
|
||||
if (this.restreamClient) {
|
||||
this.restreamClient.disconnect();
|
||||
}
|
||||
this.dashboard.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run OpenAI Realtime demo
|
||||
*/
|
||||
async runOpenAIDemo(): Promise<void> {
|
||||
if (!process.env.OPENAI_API_KEY) {
|
||||
console.log(chalk.red('❌ OPENAI_API_KEY not found in environment'));
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(chalk.bold.cyan('\n🤖 Starting OpenAI Realtime Demo\n'));
|
||||
|
||||
this.dashboard.start(100);
|
||||
|
||||
this.realtimeClient = new OpenAIRealtimeClient({
|
||||
apiKey: process.env.OPENAI_API_KEY,
|
||||
model: process.env.OPENAI_REALTIME_MODEL || 'gpt-4o-realtime-preview-2024-10-01',
|
||||
voice: 'alloy',
|
||||
});
|
||||
|
||||
this.realtimeClient.on('response.text.delta', (delta) => {
|
||||
this.dashboard.processMessage(delta, delta.length);
|
||||
});
|
||||
|
||||
this.realtimeClient.on('response.audio.delta', (delta) => {
|
||||
this.dashboard.processStream('openai-audio', Buffer.from(delta, 'base64'), 'audio');
|
||||
});
|
||||
|
||||
try {
|
||||
await this.realtimeClient.connect();
|
||||
console.log(chalk.green('✓ Connected to OpenAI Realtime API'));
|
||||
|
||||
// Send test messages
|
||||
const messages = [
|
||||
'Hello, can you help me understand patterns in conversations?',
|
||||
'What are the key characteristics of chaotic systems?',
|
||||
'Explain temporal attractors in simple terms.',
|
||||
];
|
||||
|
||||
for (const message of messages) {
|
||||
await this.sleep(5000);
|
||||
this.realtimeClient.sendText(message);
|
||||
this.dashboard.processMessage(`User: ${message}`, message.split(' ').length);
|
||||
}
|
||||
|
||||
// Run for configured duration
|
||||
await this.sleep(this.config.duration * 1000);
|
||||
|
||||
this.realtimeClient.disconnect();
|
||||
} catch (error) {
|
||||
console.error(chalk.red('Error:', error));
|
||||
}
|
||||
|
||||
this.dashboard.stop();
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// Helpers
|
||||
// ==========================================================================
|
||||
|
||||
/**
|
||||
* Sleep for specified milliseconds
|
||||
*/
|
||||
private sleep(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Main Entry Point
|
||||
// ============================================================================
|
||||
|
||||
async function main() {
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
let config: DemoConfig = {
|
||||
mode: 'all',
|
||||
simulateStream: true,
|
||||
useOpenAI: false,
|
||||
duration: 60, // 1 minute default
|
||||
};
|
||||
|
||||
// Parse command line arguments
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i];
|
||||
|
||||
if (arg === '--mode' && args[i + 1]) {
|
||||
config.mode = args[++i] as any;
|
||||
} else if (arg === '--duration' && args[i + 1]) {
|
||||
config.duration = parseInt(args[++i]);
|
||||
} else if (arg === '--no-simulate') {
|
||||
config.simulateStream = false;
|
||||
} else if (arg === '--openai') {
|
||||
config.useOpenAI = true;
|
||||
} else if (arg === '--help' || arg === '-h') {
|
||||
printHelp();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Print banner
|
||||
printBanner();
|
||||
|
||||
// Create and run demo
|
||||
const demo = new MidStreamDemo(config);
|
||||
|
||||
try {
|
||||
switch (config.mode) {
|
||||
case 'text':
|
||||
await demo.runTextDemo();
|
||||
break;
|
||||
case 'audio':
|
||||
await demo.runAudioDemo();
|
||||
break;
|
||||
case 'video':
|
||||
await demo.runVideoDemo();
|
||||
break;
|
||||
case 'all':
|
||||
if (config.useOpenAI) {
|
||||
await demo.runOpenAIDemo();
|
||||
} else {
|
||||
await demo.runFullDemo();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.log(chalk.red(`Unknown mode: ${config.mode}`));
|
||||
printHelp();
|
||||
}
|
||||
|
||||
console.log(chalk.green('\n✓ Demo completed successfully\n'));
|
||||
} catch (error) {
|
||||
console.error(chalk.red('\n❌ Demo failed:'), error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Helper Functions
|
||||
// ============================================================================
|
||||
|
||||
function printBanner() {
|
||||
console.log(chalk.bold.cyan('\n╔═══════════════════════════════════════════════════════════╗'));
|
||||
console.log(chalk.bold.cyan('║ ║'));
|
||||
console.log(chalk.bold.cyan('║ MidStream Dashboard Demo ║'));
|
||||
console.log(chalk.bold.cyan('║ ║'));
|
||||
console.log(chalk.bold.cyan('║ Real-time LLM Streaming Analysis ║'));
|
||||
console.log(chalk.bold.cyan('║ with Lean Agentic Learning ║'));
|
||||
console.log(chalk.bold.cyan('║ ║'));
|
||||
console.log(chalk.bold.cyan('║ Created by rUv ║'));
|
||||
console.log(chalk.bold.cyan('║ ║'));
|
||||
console.log(chalk.bold.cyan('╚═══════════════════════════════════════════════════════════╝\n'));
|
||||
}
|
||||
|
||||
function printHelp() {
|
||||
console.log(chalk.bold('\nUsage:') + ' npm run demo [options]\n');
|
||||
console.log(chalk.bold('Options:'));
|
||||
console.log(' --mode <mode> Demo mode: text, audio, video, all (default: all)');
|
||||
console.log(' --duration <secs> Duration in seconds (default: 60)');
|
||||
console.log(' --no-simulate Disable stream simulation');
|
||||
console.log(' --openai Use OpenAI Realtime API');
|
||||
console.log(' --help, -h Show this help message\n');
|
||||
console.log(chalk.bold('Examples:'));
|
||||
console.log(' npm run demo --mode text --duration 30');
|
||||
console.log(' npm run demo --mode all --openai');
|
||||
console.log(' npm run demo --mode video --duration 120\n');
|
||||
}
|
||||
|
||||
// Run the demo
|
||||
if (require.main === module) {
|
||||
main().catch((error) => {
|
||||
console.error(chalk.red('Fatal error:'), error);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
export { MidStreamDemo };
|
||||
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
* Example: OpenAI Realtime API with Audio
|
||||
*
|
||||
* Demonstrates audio streaming with OpenAI Realtime API
|
||||
* and real-time transcription analysis
|
||||
*/
|
||||
|
||||
import { OpenAIRealtimeClient, createDefaultSessionConfig, audioToBase64 } from '../src/openai-realtime.js';
|
||||
import * as fs from 'fs';
|
||||
import * as dotenv from 'dotenv';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
async function main() {
|
||||
const client = new OpenAIRealtimeClient({
|
||||
apiKey: process.env.OPENAI_API_KEY!,
|
||||
model: process.env.OPENAI_REALTIME_MODEL,
|
||||
voice: 'alloy',
|
||||
});
|
||||
|
||||
// Track transcriptions
|
||||
let userTranscript = '';
|
||||
let assistantTranscript = '';
|
||||
const audioChunks: string[] = [];
|
||||
|
||||
// Event listeners
|
||||
client.on('connected', () => {
|
||||
console.log('✓ Connected to OpenAI Realtime API (Audio Mode)');
|
||||
});
|
||||
|
||||
client.on('session.created', (session) => {
|
||||
console.log('✓ Session created:', session.id);
|
||||
|
||||
// Configure for audio
|
||||
client.updateSession({
|
||||
...createDefaultSessionConfig(),
|
||||
modalities: ['text', 'audio'],
|
||||
voice: 'alloy',
|
||||
instructions: 'You are a voice assistant that helps analyze conversation patterns.',
|
||||
});
|
||||
});
|
||||
|
||||
// Handle transcriptions
|
||||
client.on('conversation.item.input_audio_transcription.completed', (data) => {
|
||||
userTranscript = data.transcript;
|
||||
console.log('\n🎤 User (transcribed):', userTranscript);
|
||||
});
|
||||
|
||||
client.on('response.audio_transcript.delta', (delta) => {
|
||||
process.stdout.write(delta);
|
||||
assistantTranscript += delta;
|
||||
});
|
||||
|
||||
client.on('response.audio_transcript.done', (transcript) => {
|
||||
console.log('\n');
|
||||
console.log('🔊 Assistant (transcript):', transcript);
|
||||
});
|
||||
|
||||
// Handle audio chunks
|
||||
client.on('response.audio.delta', (delta) => {
|
||||
audioChunks.push(delta);
|
||||
});
|
||||
|
||||
client.on('response.audio.done', (data) => {
|
||||
console.log('✓ Audio response complete');
|
||||
|
||||
// Optionally save audio to file
|
||||
if (audioChunks.length > 0) {
|
||||
const audioData = Buffer.from(audioChunks.join(''), 'base64');
|
||||
fs.writeFileSync('response_audio.pcm', audioData);
|
||||
console.log(' → Audio saved to response_audio.pcm');
|
||||
audioChunks.length = 0;
|
||||
}
|
||||
});
|
||||
|
||||
client.on('response.done', () => {
|
||||
console.log('✓ Response completed\n');
|
||||
|
||||
// MidStream analysis
|
||||
const analysis = client.getMidStreamAnalysis();
|
||||
console.log('📊 Conversation Analysis:', {
|
||||
messages: analysis.messageCount,
|
||||
patterns: analysis.patterns?.length || 0,
|
||||
});
|
||||
});
|
||||
|
||||
client.on('error', (error) => {
|
||||
console.error('❌ Error:', error.message);
|
||||
});
|
||||
|
||||
// Connect
|
||||
try {
|
||||
await client.connect();
|
||||
|
||||
console.log('\n🎙️ Audio Mode Demonstration');
|
||||
console.log('═══════════════════════════════════════\n');
|
||||
|
||||
// For demo purposes, we'll send text and receive audio
|
||||
// In a real app, you'd stream audio from a microphone
|
||||
|
||||
// Demo 1: Send text, receive audio
|
||||
console.log('Sending text message (will receive audio response)...\n');
|
||||
client.sendText('Hello! Please tell me about conversation patterns.');
|
||||
|
||||
await new Promise(resolve => {
|
||||
client.once('response.done', resolve);
|
||||
});
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
// Demo 2: Simulate audio input (in real app, this would be mic audio)
|
||||
console.log('Simulating audio input...\n');
|
||||
|
||||
// In a real application, you would:
|
||||
// 1. Capture audio from microphone in PCM16 format
|
||||
// 2. Convert to base64
|
||||
// 3. Send chunks via client.sendAudio()
|
||||
// 4. Commit when done speaking
|
||||
|
||||
// For this demo, we'll send another text message
|
||||
client.sendText('Can you explain Dynamic Time Warping?');
|
||||
|
||||
await new Promise(resolve => {
|
||||
client.once('response.done', resolve);
|
||||
});
|
||||
|
||||
// Final analysis
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
console.log('\n═══════════════════════════════════════');
|
||||
console.log('📈 Final Analysis');
|
||||
console.log('═══════════════════════════════════════\n');
|
||||
|
||||
const conversation = client.getConversation();
|
||||
console.log(`Total conversation items: ${conversation.length}`);
|
||||
|
||||
const agent = client.getAgent();
|
||||
const status = agent.getStatus();
|
||||
|
||||
console.log('\n📊 MidStream Metrics:');
|
||||
console.log(` - Messages processed: ${status.conversationHistorySize}`);
|
||||
console.log(` - Reward history: ${status.rewardHistorySize}`);
|
||||
console.log(` - Average reward: ${status.averageReward.toFixed(3)}`);
|
||||
|
||||
// Cleanup
|
||||
client.disconnect();
|
||||
process.exit(0);
|
||||
} catch (error) {
|
||||
console.error('❌ Fatal error:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle graceful shutdown
|
||||
process.on('SIGINT', () => {
|
||||
console.log('\n\nShutting down...');
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* Example: OpenAI Realtime API with Text
|
||||
*
|
||||
* Demonstrates text-based conversation with OpenAI Realtime API
|
||||
* integrated with MidStream's temporal analysis
|
||||
*/
|
||||
|
||||
import { OpenAIRealtimeClient, createDefaultSessionConfig } from '../src/openai-realtime.js';
|
||||
import * as dotenv from 'dotenv';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
async function main() {
|
||||
// Create client
|
||||
const client = new OpenAIRealtimeClient({
|
||||
apiKey: process.env.OPENAI_API_KEY!,
|
||||
model: process.env.OPENAI_REALTIME_MODEL,
|
||||
voice: 'alloy',
|
||||
temperature: 0.8,
|
||||
});
|
||||
|
||||
// Set up event listeners
|
||||
client.on('connected', () => {
|
||||
console.log('✓ Connected to OpenAI Realtime API');
|
||||
});
|
||||
|
||||
client.on('session.created', (session) => {
|
||||
console.log('✓ Session created:', session.id);
|
||||
|
||||
// Update session config
|
||||
client.updateSession({
|
||||
...createDefaultSessionConfig(),
|
||||
modalities: ['text'], // Text-only for this example
|
||||
instructions: 'You are a helpful assistant that analyzes conversations in real-time.',
|
||||
});
|
||||
});
|
||||
|
||||
client.on('response.text.delta', (delta) => {
|
||||
process.stdout.write(delta);
|
||||
});
|
||||
|
||||
client.on('response.text.done', (text) => {
|
||||
console.log('\n');
|
||||
});
|
||||
|
||||
client.on('response.done', (response) => {
|
||||
console.log('✓ Response completed');
|
||||
|
||||
// Get MidStream analysis
|
||||
const analysis = client.getMidStreamAnalysis();
|
||||
console.log('\n📊 MidStream Analysis:');
|
||||
console.log(` - Messages analyzed: ${analysis.messageCount}`);
|
||||
console.log(` - Meta-learning level: ${analysis.metaLearning.currentLevel}`);
|
||||
});
|
||||
|
||||
client.on('midstream.analysis', (status) => {
|
||||
console.log('\n🧠 Real-time MidStream update:', {
|
||||
conversationSize: status.conversationHistorySize,
|
||||
averageReward: status.averageReward.toFixed(2),
|
||||
});
|
||||
});
|
||||
|
||||
client.on('error', (error) => {
|
||||
console.error('❌ Error:', error.message);
|
||||
});
|
||||
|
||||
client.on('disconnected', () => {
|
||||
console.log('✗ Disconnected from OpenAI');
|
||||
});
|
||||
|
||||
// Connect
|
||||
try {
|
||||
await client.connect();
|
||||
|
||||
// Simulate conversation
|
||||
console.log('\n💬 Starting conversation...\n');
|
||||
|
||||
// Message 1
|
||||
console.log('User: Hello! Can you help me understand patterns in conversations?');
|
||||
client.sendText('Hello! Can you help me understand patterns in conversations?');
|
||||
|
||||
// Wait for response
|
||||
await new Promise(resolve => {
|
||||
client.once('response.done', resolve);
|
||||
});
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
// Message 2
|
||||
console.log('\nUser: What are some common conversation patterns?');
|
||||
client.sendText('What are some common conversation patterns?');
|
||||
|
||||
await new Promise(resolve => {
|
||||
client.once('response.done', resolve);
|
||||
});
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
// Message 3
|
||||
console.log('\nUser: Can you give me an example?');
|
||||
client.sendText('Can you give me an example?');
|
||||
|
||||
await new Promise(resolve => {
|
||||
client.once('response.done', resolve);
|
||||
});
|
||||
|
||||
// Final analysis
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
console.log('\n\n═══════════════════════════════════════');
|
||||
console.log('📈 Final MidStream Analysis');
|
||||
console.log('═══════════════════════════════════════');
|
||||
|
||||
const finalAnalysis = client.getMidStreamAnalysis();
|
||||
console.log(JSON.stringify(finalAnalysis, null, 2));
|
||||
|
||||
const agent = client.getAgent();
|
||||
const status = agent.getStatus();
|
||||
|
||||
console.log('\n📊 Agent Status:');
|
||||
console.log(` - Conversation history: ${status.conversationHistorySize} messages`);
|
||||
console.log(` - Average reward: ${status.averageReward.toFixed(2)}`);
|
||||
console.log(` - Meta-learning: ${status.metaLearning.currentLevel}`);
|
||||
|
||||
// Cleanup
|
||||
client.disconnect();
|
||||
process.exit(0);
|
||||
} catch (error) {
|
||||
console.error('❌ Fatal error:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
+308
@@ -0,0 +1,308 @@
|
||||
#!/usr/bin/env ts-node
|
||||
/**
|
||||
* MidStream QUIC Demo
|
||||
*
|
||||
* Demonstrates QUIC protocol usage for low-latency streaming
|
||||
* with MidStream analysis
|
||||
*
|
||||
* Created by rUv
|
||||
*/
|
||||
|
||||
import {
|
||||
QuicServer,
|
||||
QuicClient,
|
||||
QuicConnection,
|
||||
createQuicServer,
|
||||
connectQuic
|
||||
} from '../src/quic-integration.js';
|
||||
import chalk from 'chalk';
|
||||
|
||||
// ============================================================================
|
||||
// Configuration
|
||||
// ============================================================================
|
||||
|
||||
const SERVER_PORT = 4433;
|
||||
const SERVER_HOST = 'localhost';
|
||||
|
||||
// ============================================================================
|
||||
// Server Example
|
||||
// ============================================================================
|
||||
|
||||
async function runServer() {
|
||||
console.log(chalk.bold.cyan('\n🚀 Starting QUIC Server Demo\n'));
|
||||
|
||||
const server = createQuicServer({
|
||||
port: SERVER_PORT,
|
||||
maxStreams: 1000
|
||||
});
|
||||
|
||||
// Handle new connections
|
||||
server.on('connection', (connection: QuicConnection) => {
|
||||
console.log(chalk.green('✓ New connection established'));
|
||||
console.log(chalk.gray(` Streams: ${connection.getStreamCount()}`));
|
||||
});
|
||||
|
||||
// Handle incoming data
|
||||
server.on('data', (data: Buffer, rinfo: any) => {
|
||||
console.log(chalk.yellow('📨 Received data:'));
|
||||
console.log(chalk.gray(` From: ${rinfo.address}:${rinfo.port}`));
|
||||
console.log(chalk.gray(` Size: ${data.length} bytes`));
|
||||
});
|
||||
|
||||
// Handle errors
|
||||
server.on('error', (error: Error) => {
|
||||
console.error(chalk.red('❌ Server error:'), error.message);
|
||||
});
|
||||
|
||||
// Start listening
|
||||
server.on('listening', (port: number) => {
|
||||
console.log(chalk.green(`✓ Server listening on port ${port}`));
|
||||
console.log(chalk.gray(` QUIC protocol ready`));
|
||||
console.log(chalk.gray(` Max streams: 1000`));
|
||||
console.log(chalk.gray(` ALPN: h3, h3-29\n`));
|
||||
});
|
||||
|
||||
await server.listen();
|
||||
|
||||
// Keep server running
|
||||
console.log(chalk.gray('Press Ctrl+C to stop server\n'));
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Client Example
|
||||
// ============================================================================
|
||||
|
||||
async function runClient() {
|
||||
console.log(chalk.bold.cyan('\n📡 Starting QUIC Client Demo\n'));
|
||||
|
||||
try {
|
||||
// Connect to server
|
||||
console.log(chalk.yellow(`Connecting to ${SERVER_HOST}:${SERVER_PORT}...`));
|
||||
const connection = await connectQuic(SERVER_HOST, SERVER_PORT);
|
||||
console.log(chalk.green('✓ Connected to QUIC server\n'));
|
||||
|
||||
// Open multiple streams
|
||||
console.log(chalk.bold('Opening multiple streams:\n'));
|
||||
|
||||
const stream1 = await connection.openBiStream({ priority: 10 });
|
||||
console.log(chalk.green('✓ Stream 1 opened (high priority)'));
|
||||
|
||||
const stream2 = await connection.openBiStream({ priority: 5 });
|
||||
console.log(chalk.green('✓ Stream 2 opened (medium priority)'));
|
||||
|
||||
const stream3 = await connection.openUniStream({ priority: 1 });
|
||||
console.log(chalk.green('✓ Stream 3 opened (low priority, unidirectional)\n'));
|
||||
|
||||
// Send data on streams
|
||||
console.log(chalk.bold('Sending data:\n'));
|
||||
|
||||
stream1.write('High priority message: Critical data');
|
||||
console.log(chalk.yellow('📤 Stream 1: Critical data sent'));
|
||||
|
||||
stream2.write('Medium priority message: Regular data');
|
||||
console.log(chalk.yellow('📤 Stream 2: Regular data sent'));
|
||||
|
||||
stream3.write('Low priority message: Background data');
|
||||
console.log(chalk.yellow('📤 Stream 3: Background data sent\n'));
|
||||
|
||||
// Get connection statistics
|
||||
const stats = connection.getStats();
|
||||
console.log(chalk.bold('Connection Statistics:\n'));
|
||||
console.log(chalk.cyan(` Streams opened: ${stats.streamsOpened}`));
|
||||
console.log(chalk.cyan(` Bytes sent: ${stats.bytesSent}`));
|
||||
console.log(chalk.cyan(` Packets sent: ${stats.packetsSent}\n`));
|
||||
|
||||
// Get MidStream analysis
|
||||
const agent = connection.getAgent();
|
||||
const analysis = agent.getStatus();
|
||||
|
||||
console.log(chalk.bold('MidStream Analysis:\n'));
|
||||
console.log(chalk.magenta(` Messages processed: ${analysis.messageCount}`));
|
||||
console.log(chalk.magenta(` Patterns detected: ${analysis.patterns.length}\n`));
|
||||
|
||||
// Close streams
|
||||
console.log(chalk.gray('Closing streams...\n'));
|
||||
stream1.close();
|
||||
stream2.close();
|
||||
stream3.close();
|
||||
|
||||
// Close connection
|
||||
connection.close();
|
||||
console.log(chalk.green('✓ Connection closed\n'));
|
||||
|
||||
} catch (error) {
|
||||
console.error(chalk.red('❌ Client error:'), error);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Multi-Stream Example
|
||||
// ============================================================================
|
||||
|
||||
async function runMultiStreamDemo() {
|
||||
console.log(chalk.bold.cyan('\n🔀 Starting Multi-Stream Demo\n'));
|
||||
|
||||
const connection = await connectQuic(SERVER_HOST, SERVER_PORT);
|
||||
console.log(chalk.green('✓ Connected\n'));
|
||||
|
||||
// Simulate multi-modal streaming
|
||||
console.log(chalk.bold('Simulating multi-modal streaming:\n'));
|
||||
|
||||
// Video stream (high priority)
|
||||
const videoStream = await connection.openBiStream({ priority: 10 });
|
||||
console.log(chalk.green('✓ Video stream opened (priority: 10)'));
|
||||
|
||||
// Audio stream (high priority)
|
||||
const audioStream = await connection.openBiStream({ priority: 9 });
|
||||
console.log(chalk.green('✓ Audio stream opened (priority: 9)'));
|
||||
|
||||
// Telemetry stream (low priority)
|
||||
const telemetryStream = await connection.openUniStream({ priority: 1 });
|
||||
console.log(chalk.green('✓ Telemetry stream opened (priority: 1)\n'));
|
||||
|
||||
// Send data on different streams
|
||||
const videoData = Buffer.alloc(1024 * 100); // 100 KB
|
||||
const audioData = Buffer.alloc(1024 * 10); // 10 KB
|
||||
const telemetryData = 'fps:30,bitrate:5000,latency:20ms';
|
||||
|
||||
console.log(chalk.bold('Streaming data:\n'));
|
||||
|
||||
videoStream.write(videoData);
|
||||
console.log(chalk.yellow('📹 Video frame sent (100 KB)'));
|
||||
|
||||
audioStream.write(audioData);
|
||||
console.log(chalk.yellow('🔊 Audio chunk sent (10 KB)'));
|
||||
|
||||
telemetryStream.write(telemetryData);
|
||||
console.log(chalk.yellow('📊 Telemetry data sent\n'));
|
||||
|
||||
// Show statistics
|
||||
const stats = connection.getStats();
|
||||
console.log(chalk.bold('Performance Metrics:\n'));
|
||||
console.log(chalk.cyan(` Total streams: ${connection.getStreamCount()}`));
|
||||
console.log(chalk.cyan(` Bytes transferred: ${stats.bytesSent}`));
|
||||
console.log(chalk.cyan(` Average latency: < 1ms (QUIC 0-RTT)\n`));
|
||||
|
||||
// Cleanup
|
||||
videoStream.close();
|
||||
audioStream.close();
|
||||
telemetryStream.close();
|
||||
connection.close();
|
||||
|
||||
console.log(chalk.green('✓ Demo complete\n'));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Performance Benchmark
|
||||
// ============================================================================
|
||||
|
||||
async function runPerformanceBenchmark() {
|
||||
console.log(chalk.bold.cyan('\n⚡ Starting Performance Benchmark\n'));
|
||||
|
||||
const connection = await connectQuic(SERVER_HOST, SERVER_PORT, {
|
||||
maxStreams: 1000
|
||||
});
|
||||
|
||||
// Benchmark: Stream creation speed
|
||||
console.log(chalk.bold('Benchmark 1: Stream Creation Speed\n'));
|
||||
|
||||
const streamCount = 100;
|
||||
const startTime = Date.now();
|
||||
|
||||
for (let i = 0; i < streamCount; i++) {
|
||||
await connection.openBiStream();
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
const streamsPerSec = Math.round((streamCount / duration) * 1000);
|
||||
|
||||
console.log(chalk.green(`✓ Created ${streamCount} streams in ${duration}ms`));
|
||||
console.log(chalk.cyan(` Rate: ${streamsPerSec} streams/sec\n`));
|
||||
|
||||
// Benchmark: Throughput
|
||||
console.log(chalk.bold('Benchmark 2: Throughput Test\n'));
|
||||
|
||||
const stream = await connection.openBiStream();
|
||||
const dataSize = 1024 * 1024; // 1 MB
|
||||
const data = Buffer.alloc(dataSize);
|
||||
|
||||
const throughputStart = Date.now();
|
||||
for (let i = 0; i < 100; i++) {
|
||||
stream.write(data);
|
||||
}
|
||||
const throughputDuration = Date.now() - throughputStart;
|
||||
|
||||
const mbTransferred = (dataSize * 100) / (1024 * 1024);
|
||||
const mbps = (mbTransferred / throughputDuration) * 1000;
|
||||
|
||||
console.log(chalk.green(`✓ Transferred ${mbTransferred.toFixed(0)} MB in ${throughputDuration}ms`));
|
||||
console.log(chalk.cyan(` Throughput: ${mbps.toFixed(2)} MB/s\n`));
|
||||
|
||||
// Show final stats
|
||||
const finalStats = connection.getStats();
|
||||
console.log(chalk.bold('Final Statistics:\n'));
|
||||
console.log(chalk.magenta(` Total streams: ${finalStats.streamsOpened}`));
|
||||
console.log(chalk.magenta(` Total bytes: ${(finalStats.bytesSent / 1024 / 1024).toFixed(2)} MB\n`));
|
||||
|
||||
connection.close();
|
||||
console.log(chalk.green('✓ Benchmark complete\n'));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Main
|
||||
// ============================================================================
|
||||
|
||||
async function main() {
|
||||
const args = process.argv.slice(2);
|
||||
const mode = args[0] || 'client';
|
||||
|
||||
console.log(chalk.bold.cyan('╔═══════════════════════════════════════════╗'));
|
||||
console.log(chalk.bold.cyan('║ MidStream QUIC Demo ║'));
|
||||
console.log(chalk.bold.cyan('║ Created by rUv ║'));
|
||||
console.log(chalk.bold.cyan('╚═══════════════════════════════════════════╝'));
|
||||
|
||||
try {
|
||||
switch (mode) {
|
||||
case 'server':
|
||||
await runServer();
|
||||
// Keep server running
|
||||
await new Promise(() => {}); // Never resolve
|
||||
break;
|
||||
|
||||
case 'client':
|
||||
await runClient();
|
||||
break;
|
||||
|
||||
case 'multistream':
|
||||
await runMultiStreamDemo();
|
||||
break;
|
||||
|
||||
case 'benchmark':
|
||||
await runPerformanceBenchmark();
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log(chalk.yellow('\nUsage: npm run quic-demo [mode]\n'));
|
||||
console.log(chalk.gray('Modes:'));
|
||||
console.log(chalk.gray(' server - Start QUIC server'));
|
||||
console.log(chalk.gray(' client - Run client demo (default)'));
|
||||
console.log(chalk.gray(' multistream - Multi-stream demo'));
|
||||
console.log(chalk.gray(' benchmark - Performance benchmark\n'));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(chalk.red('\n❌ Error:'), error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Run if called directly
|
||||
if (require.main === module) {
|
||||
main().catch((error) => {
|
||||
console.error(chalk.red('Fatal error:'), error);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
export { runServer, runClient, runMultiStreamDemo, runPerformanceBenchmark };
|
||||
@@ -0,0 +1 @@
|
||||
["greeting", "weather_query", "location_query", "weather_response", "thanks"]
|
||||
@@ -0,0 +1 @@
|
||||
["greeting", "weather_query", "location_query", "weather_response", "followup", "thanks"]
|
||||
Reference in New Issue
Block a user