refactor: config error handle, dvm-bridge improvements

This commit is contained in:
gzuuus
2025-02-08 12:44:03 +01:00
parent 1625661356
commit bf48b4517c
2 changed files with 130 additions and 21 deletions

View File

@@ -1,21 +1,71 @@
import { config } from 'dotenv'; import { config } from 'dotenv';
config(); import { join } from 'path';
import { existsSync } from 'fs';
const envPath = join(process.cwd(), '.env');
if (!existsSync(envPath)) {
throw new Error(
'No .env file found. Please create one based on .env.example'
);
}
const result = config();
if (result.error) {
throw new Error(`Error loading .env file: ${result.error.message}`);
}
const HEX_KEYS_REGEX = /^(?:[0-9a-fA-F]{64})$/;
function requireEnvVar(name: string): string {
const value = process.env[name];
if (!value) {
throw new Error(
`Missing required environment variable: ${name}. Check your .env file`
);
}
return value;
}
function getEnvVar(name: string, defaultValue: string): string {
return process.env[name] || defaultValue;
}
export const CONFIG = { export const CONFIG = {
nostr: { nostr: {
privateKey: process.env.PRIVATE_KEY!, privateKey: requireEnvVar('PRIVATE_KEY'),
relayUrls: process.env.RELAY_URLS!.split(',').map((url) => url.trim()), relayUrls: requireEnvVar('RELAY_URLS')
.split(',')
.map((url) => url.trim()),
}, },
mcp: { mcp: {
// Service info name: getEnvVar('MCP_SERVICE_NAME', 'DVM MCP Bridge'),
name: process.env.MCP_SERVICE_NAME || 'DVM MCP Bridge', about: getEnvVar(
about: 'MCP_SERVICE_ABOUT',
process.env.MCP_SERVICE_ABOUT || 'MCP-enabled DVM providing AI and computational tools'
'MCP-enabled DVM providing AI and computational tools', ),
// Client connection info clientName: requireEnvVar('MCP_CLIENT_NAME'),
clientName: process.env.MCP_CLIENT_NAME!, clientVersion: requireEnvVar('MCP_CLIENT_VERSION'),
clientVersion: process.env.MCP_CLIENT_VERSION!, serverCommand: requireEnvVar('MCP_SERVER_COMMAND'),
serverCommand: process.env.MCP_SERVER_COMMAND!, serverArgs: requireEnvVar('MCP_SERVER_ARGS').split(','),
serverArgs: process.env.MCP_SERVER_ARGS!.split(','),
}, },
}; };
if (!HEX_KEYS_REGEX.test(CONFIG.nostr.privateKey)) {
throw new Error('PRIVATE_KEY must be a 32-byte hex string');
}
CONFIG.nostr.relayUrls.forEach((url) => {
try {
new URL(url);
if (!url.startsWith('ws://') && !url.startsWith('wss://')) {
throw new Error(`Relay URL must start with ws:// or wss://: ${url}`);
}
} catch (error) {
throw new Error(`Invalid relay URL: ${url}`);
}
});
if (CONFIG.nostr.relayUrls.length === 0) {
throw new Error('At least one relay URL must be provided in RELAY_URLS');
}

View File

@@ -9,22 +9,58 @@ export class DVMBridge {
private mcpClient: MCPClientHandler; private mcpClient: MCPClientHandler;
private nostrAnnouncer: NostrAnnouncer; private nostrAnnouncer: NostrAnnouncer;
private relayHandler: RelayHandler; private relayHandler: RelayHandler;
private isRunning: boolean = false;
constructor() { constructor() {
console.log('Initializing DVM Bridge...');
this.mcpClient = new MCPClientHandler(); this.mcpClient = new MCPClientHandler();
this.nostrAnnouncer = new NostrAnnouncer(); this.nostrAnnouncer = new NostrAnnouncer();
this.relayHandler = new RelayHandler(CONFIG.nostr.relayUrls); this.relayHandler = new RelayHandler(CONFIG.nostr.relayUrls);
} }
async start() { async start() {
await this.mcpClient.connect(); if (this.isRunning) {
console.log('Bridge is already running');
return;
}
const tools = await this.mcpClient.listTools(); console.log('Starting DVM Bridge...');
console.log('Available MCP tools:', tools); try {
console.log('Connecting to MCP server...');
await this.mcpClient.connect();
await this.nostrAnnouncer.announceService(); const tools = await this.mcpClient.listTools();
console.log('Available MCP tools:', tools);
this.relayHandler.subscribeToRequests(this.handleRequest.bind(this)); console.log('Announcing service to Nostr network...');
await this.nostrAnnouncer.announceService();
console.log('Setting up request handlers...');
this.relayHandler.subscribeToRequests(this.handleRequest.bind(this));
this.isRunning = true;
console.log('DVM Bridge is now running and ready to handle requests');
} catch (error) {
console.error('Failed to start DVM Bridge:', error);
throw error;
}
}
async stop() {
if (!this.isRunning) {
return;
}
console.log('Stopping DVM Bridge...');
try {
await this.mcpClient.disconnect();
this.relayHandler.cleanup();
this.isRunning = false;
console.log('DVM Bridge stopped successfully');
} catch (error) {
console.error('Error stopping DVM Bridge:', error);
throw error;
}
} }
private async handleRequest(event: Event) { private async handleRequest(event: Event) {
@@ -100,9 +136,32 @@ export class DVMBridge {
console.error('Error handling request:', error); console.error('Error handling request:', error);
} }
} }
}
async stop() { if (import.meta.main) {
await this.mcpClient.disconnect(); console.log('Starting DVM-MCP Bridge service...');
this.relayHandler.cleanup(); const bridge = new DVMBridge();
const shutdown = async () => {
console.log('Shutting down...');
try {
await bridge.stop();
process.exit(0);
} catch (error) {
console.error('Error during shutdown:', error);
process.exit(1);
}
};
// Handle termination signals
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
// Start the bridge
try {
await bridge.start();
} catch (error) {
console.error('Failed to start service:', error);
process.exit(1);
} }
} }