james-d-taboola's picture
feat: add init commit according to Issac's repo
4018140
import { generateText } from 'ai';
import { allTools, getToolByName } from './tools';
import { z } from 'zod';
import {
Message,
AgentContext,
AgentConfig,
AgentType,
PromptLog
} from './types/agent';
export class AIAgent {
public contexts: Map<string, AgentContext> = new Map();
private model: any;
public config: AgentConfig;
private promptLogs: PromptLog[] = [];
constructor(model: any, config: AgentConfig) {
this.model = model;
this.config = config;
console.log(`AI Agent initialized: ${config.name} (${config.type}:${config.personality}) with tools:`, config.availableTools);
}
getConfig(): AgentConfig {
return { ...this.config };
}
updateConfig(newConfig: AgentConfig): void {
this.config = { ...newConfig };
this.config.updatedAt = new Date().toISOString();
console.log(`Agent ${this.config.id} config updated`);
}
private getSystemPrompt(): string {
return this.config.systemPrompt;
}
getOrCreateContext(conversationId: string): AgentContext {
if (!this.contexts.has(conversationId)) {
this.contexts.set(conversationId, {
conversationId,
messages: [
{
role: 'system',
content: this.getSystemPrompt(),
timestamp: new Date().toISOString()
}
],
availableTools: this.config.availableTools
});
}
return this.contexts.get(conversationId)!;
}
async chat(conversationId: string, userMessage: string): Promise<string> {
const context = this.getOrCreateContext(conversationId);
const timestamp = new Date().toISOString();
// Add user message to context
context.messages.push({
role: 'user',
content: userMessage,
timestamp
});
let toolsUsed: string[] = [];
try {
// Generate response using the AI model
const { text } = await generateText({
model: this.model,
messages: context.messages.map(msg => ({
role: msg.role,
content: msg.content
}))
});
// Check if the response indicates tool usage
let finalResponse = text;
try {
const parsed = JSON.parse(text);
if (parsed.action === 'use_tool') {
toolsUsed.push(parsed.tool);
// Execute the tool
const toolResult = await this.executeTool(parsed.tool, parsed.parameters);
// Generate a follow-up response incorporating the tool result
const followUpMessages = [
...context.messages,
{ role: 'assistant' as const, content: text },
{ role: 'user' as const, content: `Tool result: ${toolResult}. Please provide a helpful response to the user based on this information.` }
];
const { text: followUpText } = await generateText({
model: this.model,
messages: followUpMessages
});
finalResponse = followUpText;
}
} catch {
// If parsing fails, treat as regular response
}
// Add assistant response to context
context.messages.push({
role: 'assistant',
content: finalResponse,
timestamp: new Date().toISOString()
});
// Log the interaction for future persistence
this.logPrompt({
agentId: this.config.id,
conversationId,
timestamp,
promptVersion: '1.0', // TODO: Implement versioning
userMessage,
agentResponse: finalResponse,
toolsUsed,
metadata: {
agentType: this.config.type,
personality: this.config.personality
}
});
return finalResponse;
} catch (error) {
console.error(`Agent ${this.config.id} chat error:`, error);
return 'Sorry, I encountered an error while processing your request. Please try again.';
}
}
private async executeTool(toolName: string, parameters: any): Promise<string> {
// Check if tool is available for this agent
if (!this.config.availableTools.includes(toolName)) {
return `Error: Tool "${toolName}" is not available for this agent. Available tools: ${this.config.availableTools.join(', ')}`;
}
const tool = getToolByName(toolName);
if (!tool) {
return `Error: Tool "${toolName}" not found. Available tools: ${this.config.availableTools.join(', ')}`;
}
try {
// Validate parameters
const validatedParams = tool.parameters.parse(parameters);
// Execute the tool
const result = await tool.execute(validatedParams);
return result;
} catch (error) {
return `Error executing tool "${toolName}": ${error}`;
}
}
getConversationHistory(conversationId: string): Message[] {
const context = this.contexts.get(conversationId);
return context ? context.messages.filter(msg => msg.role !== 'system') : [];
}
clearConversation(conversationId: string): void {
this.contexts.delete(conversationId);
}
listAvailableTools(): Array<{name: string, description: string}> {
return allTools
.filter(tool => this.config.availableTools.includes(tool.name))
.map(tool => ({
name: tool.name,
description: tool.description
}));
}
// New methods for logging and persistence preparation
private logPrompt(log: PromptLog): void {
this.promptLogs.push(log);
// In the future, this could send to Langfuse or other persistence layer
console.log(`[${this.config.name}] Logged interaction: ${log.conversationId}`);
}
getPromptLogs(conversationId?: string): PromptLog[] {
if (conversationId) {
return this.promptLogs.filter(log => log.conversationId === conversationId);
}
return [...this.promptLogs];
}
getAgentInfo(): {
id: string;
type: AgentType;
personality: string;
name: string;
description: string;
isActive: boolean;
conversationCount: number;
lastUsed: string;
availableTools: string[];
} {
const conversationCount = this.contexts.size;
const lastLog = this.promptLogs[this.promptLogs.length - 1];
return {
id: this.config.id,
type: this.config.type,
personality: this.config.personality as string,
name: this.config.name,
description: this.config.description,
isActive: true,
conversationCount,
lastUsed: lastLog?.timestamp || this.config.createdAt,
availableTools: this.config.availableTools
};
}
// Clean up inactive conversations (optional utility)
cleanupOldConversations(maxAgeMs: number = 24 * 60 * 60 * 1000): void {
const cutoff = Date.now() - maxAgeMs;
const toDelete: string[] = [];
this.contexts.forEach((context, conversationId) => {
const lastMessage = context.messages[context.messages.length - 1];
if (lastMessage?.timestamp) {
const messageTime = new Date(lastMessage.timestamp).getTime();
if (messageTime < cutoff) {
toDelete.push(conversationId);
}
}
});
toDelete.forEach(id => {
this.contexts.delete(id);
});
if (toDelete.length > 0) {
console.log(`Agent ${this.config.id} cleaned up ${toDelete.length} old conversations`);
}
}
}