UNPKG

@robota-sdk/sessions

Version:

Session and chat management for Robota SDK - multi-session support with independent workspaces

385 lines (381 loc) 10.9 kB
import { AgentFactory, AgentTemplates, Robota } from '@robota-sdk/agents'; export { ConversationHistory, ConversationSession } from '@robota-sdk/agents'; // src/adapters/template-manager-adapter.ts var TemplateManagerAdapter = class { agentFactory; agentTemplates; constructor(agentFactory) { this.agentFactory = agentFactory || new AgentFactory(); this.agentTemplates = new AgentTemplates(); } /** * Get template configuration by name */ getTemplate(name) { const template = this.agentTemplates.getTemplate(name); if (!template) { return void 0; } return template.config; } /** * List all available template names */ listTemplates() { const templates = this.agentTemplates.getTemplates(); return templates.map((template) => template.id); } /** * Validate template configuration */ validateTemplate(config) { try { const validation = this.agentFactory.validateConfiguration(config); return validation.isValid; } catch { return !!(config.name && config.aiProviders && config.defaultModel); } } /** * Register a new template */ registerTemplate(template) { this.agentTemplates.registerTemplate(template); } /** * Unregister a template */ unregisterTemplate(templateId) { return this.agentTemplates.unregisterTemplate(templateId); } /** * Get template details (full template object) */ getTemplateDetails(name) { return this.agentTemplates.getTemplate(name); } /** * Apply template to create agent config with overrides */ applyTemplate(templateId, overrides = {}) { const template = this.agentTemplates.getTemplate(templateId); if (!template) { return void 0; } const result = this.agentFactory.applyTemplate(template, overrides); return result.config; } }; // src/chat/chat-instance.ts var ChatInstance = class { metadata; config; robota; templateManager; constructor(metadata, config, robota) { this.metadata = metadata; this.config = config; this.robota = robota; this.templateManager = new TemplateManagerAdapter(); } /** * Send a message and get AI response */ async sendMessage(content) { try { const response = await this.robota.run(content); this.metadata.messageCount++; this.metadata.lastAccessedAt = /* @__PURE__ */ new Date(); return response; } catch (error) { throw new Error(`Failed to send message: ${error instanceof Error ? error.message : "Unknown error"}`); } } /** * Regenerate the last response */ async regenerateResponse() { const history = this.robota.getHistory(); const lastUserMessage = history.filter((msg) => msg.role === "user").pop(); if (!lastUserMessage) { throw new Error("No user message found to regenerate response for"); } return this.sendMessage(lastUserMessage.content); } /** * Update robota configuration */ async updateRobotaConfig(config) { try { await this.robota.configure(config); this.config.robotaConfig = { ...this.config.robotaConfig, ...config }; this.metadata.updatedAt = /* @__PURE__ */ new Date(); } catch (error) { throw new Error(`Failed to update robota config: ${error instanceof Error ? error.message : "Unknown error"}`); } } /** * Get current robota configuration */ getRobotaConfig() { return this.config.robotaConfig; } /** * Upgrade to use an agent template */ async upgradeToTemplate(templateName) { const template = this.templateManager.getTemplate(templateName); if (!template) { throw new Error(`Template '${templateName}' not found`); } await this.updateRobotaConfig(template); this.config.agentTemplate = templateName; } /** * Get template manager instance */ getTemplateManager() { return this.templateManager; } /** * Activate this chat session */ activate() { this.metadata.isActive = true; this.metadata.lastAccessedAt = /* @__PURE__ */ new Date(); } /** * Deactivate this chat session */ deactivate() { this.metadata.isActive = false; } /** * Get conversation history - delegate to Robota */ getHistory() { return this.robota.getHistory(); } /** * Clear conversation history - delegate to Robota */ clearHistory() { this.robota.clearHistory(); this.metadata.messageCount = 0; this.metadata.updatedAt = /* @__PURE__ */ new Date(); } /** * Save chat state */ async save() { throw new Error("Chat persistence not yet implemented"); } /** * Load chat state */ async load() { throw new Error("Chat loading not yet implemented"); } /** * Get chat statistics */ getStats() { return { messageCount: this.metadata.messageCount, createdAt: this.metadata.createdAt, lastActivity: this.metadata.lastAccessedAt // TODO: Get token usage from Robota if available }; } /** * Update chat configuration */ updateConfig(config) { Object.assign(this.config, config); this.metadata.updatedAt = /* @__PURE__ */ new Date(); } }; var SessionManager = class { sessions = /* @__PURE__ */ new Map(); chats = /* @__PURE__ */ new Map(); sessionChats = /* @__PURE__ */ new Map(); // sessionId -> chatIds agentFactory; config; constructor(config = {}) { this.config = { maxSessions: config.maxSessions || 50, maxChatsPerSession: config.maxChatsPerSession || 10 }; this.agentFactory = new AgentFactory({ maxConcurrentAgents: this.config.maxSessions * this.config.maxChatsPerSession }); } /** * Create a new session (workspace) */ createSession(options = {}) { if (this.sessions.size >= this.config.maxSessions) { throw new Error(`Maximum sessions limit (${this.config.maxSessions}) reached. Please remove existing sessions before creating new ones.`); } const sessionId = this.generateSessionId(); const sessionInfo = { id: sessionId, userId: options.userId || "anonymous", name: options.name || `Session ${sessionId.slice(-8)}`, state: "active" /* ACTIVE */, chatCount: 0, createdAt: /* @__PURE__ */ new Date(), lastUsedAt: /* @__PURE__ */ new Date(), ...options.workspaceId && { workspaceId: options.workspaceId } }; this.sessions.set(sessionId, sessionInfo); this.sessionChats.set(sessionId, /* @__PURE__ */ new Set()); return sessionId; } /** * Create a new chat (AI agent) within a session */ async createChat(sessionId, options) { const session = this.sessions.get(sessionId); if (!session) { throw new Error(`Session ${sessionId} not found`); } const sessionChatIds = this.sessionChats.get(sessionId); if (sessionChatIds.size >= this.config.maxChatsPerSession) { throw new Error(`Maximum chats per session (${this.config.maxChatsPerSession}) reached`); } const chatId = this.generateChatId(); const robota = await this.agentFactory.createAgent(Robota, options.agentConfig); const metadata = { chatId, sessionId, chatName: options.name || `Chat ${chatId.slice(-8)}`, createdAt: /* @__PURE__ */ new Date(), updatedAt: /* @__PURE__ */ new Date(), lastAccessedAt: /* @__PURE__ */ new Date(), messageCount: 0, isActive: false, ...options.description && { description: options.description } }; const chatConfig = { robotaConfig: options.agentConfig, ...options.name && { chatName: options.name }, ...options.description && { description: options.description }, ...options.agentTemplate && { agentTemplate: options.agentTemplate } }; const chatInstance = new ChatInstance(metadata, chatConfig, robota); this.chats.set(chatId, chatInstance); sessionChatIds.add(chatId); session.chatCount++; session.lastUsedAt = /* @__PURE__ */ new Date(); return chatId; } /** * Get a chat instance */ getChat(chatId) { return this.chats.get(chatId); } /** * Get session information */ getSession(sessionId) { return this.sessions.get(sessionId); } /** * List all chats in a session */ getSessionChats(sessionId) { const chatIds = this.sessionChats.get(sessionId); if (!chatIds) { return []; } return Array.from(chatIds).map((chatId) => this.chats.get(chatId)).filter((chat) => chat !== void 0).map((chat) => ({ id: chat.metadata.chatId, sessionId: chat.metadata.sessionId, name: chat.metadata.chatName, isActive: chat.metadata.isActive, messageCount: chat.metadata.messageCount, createdAt: chat.metadata.createdAt, lastUsedAt: chat.metadata.lastAccessedAt, ...chat.config.agentTemplate && { agentTemplate: chat.config.agentTemplate } })); } /** * Switch active chat in session */ switchChat(sessionId, chatId) { const session = this.sessions.get(sessionId); const chat = this.chats.get(chatId); if (!session || !chat || chat.metadata.sessionId !== sessionId) { return false; } if (session.activeChatId) { const currentChat = this.chats.get(session.activeChatId); currentChat?.deactivate(); } chat.activate(); session.activeChatId = chatId; session.lastUsedAt = /* @__PURE__ */ new Date(); return true; } /** * Delete a chat */ deleteChat(chatId) { const chat = this.chats.get(chatId); if (!chat) { return false; } const sessionId = chat.metadata.sessionId; const session = this.sessions.get(sessionId); const sessionChatIds = this.sessionChats.get(sessionId); if (session && sessionChatIds) { sessionChatIds.delete(chatId); session.chatCount--; if (session.activeChatId === chatId) { delete session.activeChatId; } } this.chats.delete(chatId); return true; } /** * Delete a session and all its chats */ deleteSession(sessionId) { const session = this.sessions.get(sessionId); if (!session) { return false; } const chatIds = this.sessionChats.get(sessionId); if (chatIds) { for (const chatId of chatIds) { this.chats.delete(chatId); } } this.sessions.delete(sessionId); this.sessionChats.delete(sessionId); return true; } /** * List all sessions */ listSessions() { return Array.from(this.sessions.values()); } /** * Generate unique session ID */ generateSessionId() { return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } /** * Generate unique chat ID */ generateChatId() { return `chat_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } }; export { ChatInstance, SessionManager, TemplateManagerAdapter };