contextManager.ts•11.3 kB
import {
ContextType,
ContextPriority,
ContextState,
ContextTrigger,
ContextSwitchRequest,
ContextSwitchResponse,
ContextStack,
MultiModalContext
} from './types';
import { v4 as uuidv4 } from 'uuid';
import { config } from '../config';
import { MemoryManager } from '../memory/memoryManager';
import { ImportanceLevel, MemoryType } from '../memory/types';
/**
* Manager for handling real-time context switching
*/
export class ContextManager {
private contextStacks: Map<string, ContextStack> = new Map();
private contextTriggers: Map<string, ContextTrigger> = new Map();
private memoryManager: MemoryManager;
constructor(memoryManager: MemoryManager) {
this.memoryManager = memoryManager;
this.initializeDefaultTriggers();
}
/**
* Initialize default context triggers from config
*/
private initializeDefaultTriggers(): void {
if (config.context && config.context.triggers) {
// Process task triggers
if (config.context.triggers.task) {
for (const pattern of config.context.triggers.task) {
const trigger: ContextTrigger = {
id: uuidv4(),
pattern,
contextType: ContextType.TASK,
contextValue: 'specific',
description: `Task trigger for pattern: ${pattern}`,
isActive: true
};
this.contextTriggers.set(trigger.id, trigger);
}
}
// Process tone triggers
if (config.context.triggers.tone) {
for (const pattern of config.context.triggers.tone) {
const trigger: ContextTrigger = {
id: uuidv4(),
pattern,
contextType: ContextType.TONE,
contextValue: pattern.includes('formal') ? 'formal' :
pattern.includes('casual') ? 'casual' :
pattern.includes('professional') ? 'professional' :
pattern.includes('creative') ? 'creative' :
pattern.includes('technical') ? 'technical' : 'neutral',
description: `Tone trigger for pattern: ${pattern}`,
isActive: true
};
this.contextTriggers.set(trigger.id, trigger);
}
}
// Process domain triggers
if (config.context.triggers.domain) {
for (const pattern of config.context.triggers.domain) {
const trigger: ContextTrigger = {
id: uuidv4(),
pattern,
contextType: ContextType.DOMAIN,
contextValue: pattern.includes('marketing') ? 'marketing' :
pattern.includes('technical') ? 'technical' :
pattern.includes('creative') ? 'creative' : 'general',
description: `Domain trigger for pattern: ${pattern}`,
isActive: true
};
this.contextTriggers.set(trigger.id, trigger);
}
}
}
}
/**
* Initialize a context stack for an agent if it doesn't exist
*/
private ensureContextStack(agentId: string): ContextStack {
if (!this.contextStacks.has(agentId)) {
// Create default context states for each type
const defaultContexts: Record<ContextType, ContextState> = {
[ContextType.TONE]: {
id: uuidv4(),
type: ContextType.TONE,
value: 'neutral',
priority: ContextPriority.MEDIUM,
createdAt: Date.now(),
updatedAt: Date.now()
},
[ContextType.TASK]: {
id: uuidv4(),
type: ContextType.TASK,
value: 'general',
priority: ContextPriority.HIGH,
createdAt: Date.now(),
updatedAt: Date.now()
},
[ContextType.ROLE]: {
id: uuidv4(),
type: ContextType.ROLE,
value: 'assistant',
priority: ContextPriority.HIGH,
createdAt: Date.now(),
updatedAt: Date.now()
},
[ContextType.DOMAIN]: {
id: uuidv4(),
type: ContextType.DOMAIN,
value: 'general',
priority: ContextPriority.MEDIUM,
createdAt: Date.now(),
updatedAt: Date.now()
},
[ContextType.USER]: {
id: uuidv4(),
type: ContextType.USER,
value: 'default',
priority: ContextPriority.HIGH,
createdAt: Date.now(),
updatedAt: Date.now()
},
[ContextType.ENVIRONMENT]: {
id: uuidv4(),
type: ContextType.ENVIRONMENT,
value: 'default',
priority: ContextPriority.LOW,
createdAt: Date.now(),
updatedAt: Date.now()
},
[ContextType.MULTIMODAL]: {
id: uuidv4(),
type: ContextType.MULTIMODAL,
value: 'none',
priority: ContextPriority.MEDIUM,
createdAt: Date.now(),
updatedAt: Date.now()
}
};
const contextStack: ContextStack = {
agentId,
stack: Object.values(defaultContexts),
current: defaultContexts
};
this.contextStacks.set(agentId, contextStack);
}
return this.contextStacks.get(agentId)!;
}
/**
* Switch context for an agent
*/
public async switchContext(request: ContextSwitchRequest): Promise<ContextSwitchResponse> {
const { agentId, contextType, contextValue, priority = ContextPriority.MEDIUM, metadata = {} } = request;
// Ensure context stack exists
const contextStack = this.ensureContextStack(agentId);
// Get previous context
const previousContext = contextStack.current[contextType];
// Create new context
const newContext: ContextState = {
id: uuidv4(),
type: contextType,
value: contextValue,
priority,
metadata,
createdAt: Date.now(),
updatedAt: Date.now()
};
// Update context stack
contextStack.stack.push(newContext);
contextStack.current[contextType] = newContext;
// Store context change in memory
await this.memoryManager.storeMemory({
roleId: agentId,
content: `Context switched: ${contextType} from '${previousContext.value}' to '${contextValue}'`,
type: MemoryType.SESSION,
importance: ImportanceLevel.MEDIUM,
metadata: {
type: 'context_switch',
contextType,
previousValue: previousContext.value,
newValue: contextValue,
priority
}
});
return {
success: true,
message: `Context switched: ${contextType} from '${previousContext.value}' to '${contextValue}'`,
previousContext,
newContext
};
}
/**
* Get current context for an agent
*/
public getCurrentContext(agentId: string): Record<ContextType, ContextState> {
const contextStack = this.ensureContextStack(agentId);
return contextStack.current;
}
/**
* Get context history for an agent
*/
public getContextHistory(agentId: string): ContextState[] {
const contextStack = this.ensureContextStack(agentId);
return [...contextStack.stack];
}
/**
* Add a new context trigger
*/
public addContextTrigger(trigger: Omit<ContextTrigger, 'id'>): ContextTrigger {
const newTrigger: ContextTrigger = {
...trigger,
id: uuidv4(),
isActive: true
};
this.contextTriggers.set(newTrigger.id, newTrigger);
return newTrigger;
}
/**
* Update an existing context trigger
*/
public updateContextTrigger(triggerId: string, updates: Partial<Omit<ContextTrigger, 'id'>>): ContextTrigger {
const existingTrigger = this.contextTriggers.get(triggerId);
if (!existingTrigger) {
throw new Error(`Trigger with ID ${triggerId} not found`);
}
const updatedTrigger: ContextTrigger = {
...existingTrigger,
...updates
};
this.contextTriggers.set(triggerId, updatedTrigger);
return updatedTrigger;
}
/**
* Delete a context trigger
*/
public deleteContextTrigger(triggerId: string): boolean {
return this.contextTriggers.delete(triggerId);
}
/**
* Get all context triggers
*/
public getAllContextTriggers(): ContextTrigger[] {
return Array.from(this.contextTriggers.values());
}
/**
* Check input for context triggers and apply if matched
*/
public async checkAndApplyTriggers(agentId: string, input: string): Promise<ContextSwitchResponse[]> {
const responses: ContextSwitchResponse[] = [];
for (const trigger of this.contextTriggers.values()) {
if (!trigger.isActive) continue;
const pattern = trigger.pattern instanceof RegExp
? trigger.pattern
: new RegExp(trigger.pattern, 'i');
if (pattern.test(input)) {
// Trigger matched, apply context switch
const response = await this.switchContext({
agentId,
contextType: trigger.contextType,
contextValue: trigger.contextValue,
triggerId: trigger.id
});
responses.push(response);
}
}
return responses;
}
/**
* Generate context-aware prompt modifications
*/
public generateContextPromptModifiers(agentId: string): string {
const contextStack = this.ensureContextStack(agentId);
const currentContext = contextStack.current;
let modifiers = '';
// Add tone context
if (currentContext[ContextType.TONE]) {
modifiers += `\n\nTone: Please respond in a ${currentContext[ContextType.TONE].value} tone.`;
}
// Add task context
if (currentContext[ContextType.TASK]) {
modifiers += `\n\nTask: You are currently focused on ${currentContext[ContextType.TASK].value}.`;
}
// Add role context
if (currentContext[ContextType.ROLE]) {
modifiers += `\n\nRole: You are acting as a ${currentContext[ContextType.ROLE].value}.`;
}
// Add domain context
if (currentContext[ContextType.DOMAIN]) {
modifiers += `\n\nDomain: Prioritize knowledge about ${currentContext[ContextType.DOMAIN].value}.`;
}
// Add user context
if (currentContext[ContextType.USER]) {
modifiers += `\n\nUser: Consider the user's preferences: ${currentContext[ContextType.USER].value}.`;
}
// Add environment context
if (currentContext[ContextType.ENVIRONMENT]) {
modifiers += `\n\nEnvironment: Consider the current environment: ${currentContext[ContextType.ENVIRONMENT].value}.`;
}
// Add multimodal context
if (currentContext[ContextType.MULTIMODAL] && currentContext[ContextType.MULTIMODAL].value !== 'none') {
modifiers += `\n\nMultimodal: Consider the multimodal context: ${currentContext[ContextType.MULTIMODAL].value}.`;
}
return modifiers;
}
/**
* Handle multi-modal context
*/
public async handleMultiModalContext(agentId: string, context: MultiModalContext): Promise<void> {
// Store multi-modal context in memory
await this.memoryManager.storeMemory({
roleId: agentId,
content: context.text || 'Multi-modal context added',
type: MemoryType.SESSION,
importance: ImportanceLevel.MEDIUM,
metadata: {
type: 'multi_modal_context',
imageUrls: context.imageUrls,
priority: context.priority,
...context.metadata
}
});
}
}