UNPKG

@agentscope/studio

Version:

AgentScope Studio is a powerful local monitoring and visualization tool designed to provide real-time insights into your system's performance and behavior.

212 lines (211 loc) 10 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const trpcExpress = __importStar(require("@trpc/server/adapters/express")); const express_1 = __importDefault(require("express")); const http_1 = require("http"); const opener_1 = __importDefault(require("opener")); const path_1 = __importDefault(require("path")); const portfinder_1 = __importDefault(require("portfinder")); const config_1 = require("../../shared/src/config"); const banner_1 = require("../../shared/src/utils/banner"); const terminal_1 = require("../../shared/src/utils/terminal"); const database_1 = require("./database"); const grpc_server_1 = require("./otel/grpc-server"); const router_1 = __importDefault(require("./otel/router")); const router_2 = require("./trpc/router"); const socket_1 = require("./trpc/socket"); function initializeServer() { return __awaiter(this, void 0, void 0, function* () { try { // Initialize the configuration const configManager = config_1.ConfigManager.getInstance(); const config = configManager.getConfig(); portfinder_1.default.basePort = config.port; portfinder_1.default.highestPort = portfinder_1.default.basePort + 2000; // Handle HTTP port const availableHttpPort = yield portfinder_1.default.getPortPromise(); if (availableHttpPort !== config.port) { console.log(`HTTP port ${config.port} is already in use.`); // Check if running in interactive environment const isInteractive = process.stdin.isTTY && process.stdout.isTTY; let useNewPort; if (isInteractive) { useNewPort = yield (0, terminal_1.promptUser)(`Would you like to start the HTTP server on port ${availableHttpPort} instead? (y/n): `); } else { // Non-interactive mode: automatically use available port console.log(`Automatically using available HTTP port ${availableHttpPort} (non-interactive mode)`); useNewPort = true; } if (useNewPort) { yield configManager.setPort(availableHttpPort); console.log(`HTTP server will start on port ${availableHttpPort}`); } else { console.log('Exiting...'); process.exit(1); } } // Handle gRPC port portfinder_1.default.basePort = config.otelGrpcPort; portfinder_1.default.highestPort = portfinder_1.default.basePort + 2000; const availableGrpcPort = yield portfinder_1.default.getPortPromise(); if (availableGrpcPort !== config.otelGrpcPort) { console.log(`[OTEL gRPC] port ${config.otelGrpcPort} is already in use.`); // Check if running in interactive environment const isInteractive = process.stdin.isTTY && process.stdout.isTTY; let useNewPort; if (isInteractive) { useNewPort = yield (0, terminal_1.promptUser)(`Would you like to start the OTEL gRPC server on port ${availableGrpcPort} instead? (y/n): `); } else { // Non-interactive mode: automatically use available port console.log(`Automatically using available OTEL gRPC port ${availableGrpcPort} (non-interactive mode)`); useNewPort = true; } if (useNewPort) { yield configManager.setOtelGrpcPort(availableGrpcPort); console.log(`OTEL gRPC server will start on port ${availableGrpcPort}`); } else { console.log('Exiting...'); process.exit(1); } } // Create APP instance const app = (0, express_1.default)(); const httpServer = (0, http_1.createServer)(app); // Initialize the database yield (0, database_1.initializeDatabase)(config.database); // Set TRPC router app.use('/trpc', trpcExpress.createExpressMiddleware({ router: router_2.appRouter, })); app.use('/v1', express_1.default.raw({ type: [ 'application/x-protobuf', 'application/vnd.google.protobuf', 'application/protobuf', 'application/octet-stream', 'application/json', ], limit: '10mb', }), router_1.default); // Initialize SocketManager socket_1.SocketManager.init(httpServer); // Initialize and start OTEL gRPC server on a separate port const actualGrpcPort = configManager.getConfig().otelGrpcPort; const otelGrpcServer = new grpc_server_1.OtelGrpcServer(); try { yield otelGrpcServer.start(actualGrpcPort); } catch (error) { console.warn(`Failed to start OTEL gRPC server on port ${actualGrpcPort}, ` + 'traces will be received via HTTP endpoint /v1/traces:', error instanceof Error ? error.message : error); } // Serve static files in development mode if (process.env.NODE_ENV === 'production') { const publicPath = path_1.default.join(__dirname, '../../public'); app.use(express_1.default.static(publicPath)); app.use((req, res, next) => { if (!req.path.startsWith('/trpc')) { res.sendFile(path_1.default.join(publicPath, 'index.html'), { dotfiles: 'allow', }); } else { next(); } }); } httpServer.listen(configManager.getConfig().port, () => { const actualPort = configManager.getConfig().port; const config = configManager.getConfig(); const mode = (process.env.NODE_ENV || 'production'); // Display startup banner (0, banner_1.displayBanner)(config_1.APP_INFO.name.replace('-', '\n'), config_1.APP_INFO.version, actualPort, actualGrpcPort, config.database.database, mode); if (process.env.NODE_ENV === 'production') { (0, opener_1.default)(`http://localhost:${actualPort}/home`); } }); return { httpServer, otelGrpcServer }; } catch (error) { console.error('Error initializing server:', error); console.error('Error stack:', error.stack); throw error; } }); } // Set up the server and start listening initializeServer() .then(({ httpServer, otelGrpcServer }) => { // Handle graceful shutdown const cleanup = () => __awaiter(void 0, void 0, void 0, function* () { console.debug('Closing Socket.IO connections'); socket_1.SocketManager.close(); console.debug('Stopping gRPC server'); try { yield otelGrpcServer.stop(); } catch (error) { console.error('Error stopping gRPC server:', error); otelGrpcServer.forceShutdown(); } console.debug('Closing HTTP server'); httpServer.close(() => { console.debug('HTTP server closed'); process.exit(0); }); }); process.on('SIGTERM', cleanup); process.on('SIGINT', cleanup); }) .catch(() => { process.exit(1); });