@robota-sdk/sessions
Version:
Session and chat management for Robota SDK - multi-session support with independent workspaces
385 lines (381 loc) • 10.9 kB
JavaScript
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 };