@simonecoelhosfo/optimizely-mcp-server
Version:
Optimizely MCP Server for AI assistants with integrated CLI tools
313 lines • 11.6 kB
TypeScript
/**
* Entity Orchestrator for Complex Multi-Step Entity Creation
* @description Handles complex entity creation workflows that require multiple API calls
* in a specific sequence with rollback capabilities for partial failures.
*
* Key Responsibilities:
* - Orchestrate multi-step entity creation (e.g., Flag + Variables + A/B Test)
* - Handle dependencies between entity creation steps
* - Provide rollback functionality for partial failures
* - Track creation progress for debugging and error reporting
*
* @author Optimizely MCP Server
* @version 1.0.0
*/
import { OptimizelyAPIHelper } from '../api/OptimizelyAPIHelper.js';
import { ProcessedTemplate } from '../utils/TemplateProcessor.js';
import { EntityRouter } from '../tools/EntityRouter.js';
export interface OrchestrationStep {
stepName: string;
operation: 'create' | 'update' | 'delete' | 'get' | 'wait';
entityType: string;
data: any;
dependencies?: string[];
rollbackData?: any;
options?: Record<string, any>;
optional?: boolean;
}
export interface OrchestrationResult {
success: boolean;
orchestration_summary?: {
headline: string;
operation_type: 'flag_with_ab_test' | 'experiment_with_pages' | 'simple_entity' | 'multi_entity';
components: {
created_count: number;
adopted_count: number;
details: {
variations?: string;
metrics?: string;
pages?: string;
traffic_split?: string;
environment?: string;
};
};
facts: {
project_id: string;
project_name?: string;
environment?: string;
flag_key?: string;
experiment_id?: string;
[key: string]: any;
};
auto_decisions?: Array<{
field: string;
value: any;
reason: string;
}>;
};
created_entities: CreatedEntity[];
createdEntities: CreatedEntity[];
adoptedEntities?: AdoptedEntity[];
errors: string[];
rollbackLog?: string[];
executionTimeMs: number;
summary?: string;
autoCorrections?: {
totalCorrections: number;
correctionsByEntity: Record<string, any[]>;
userMessage: string;
};
finalFlagState?: any;
metrics_created?: Array<{
key: string;
id: string;
name?: string;
step_name: string;
}>;
}
export interface CreatedEntity {
stepName: string;
entityType: string;
entityId: string;
entityKey?: string;
rollbackData?: any;
finalData?: any;
}
export interface AdoptedEntity {
stepName: string;
entityType: string;
entityId: string;
entityKey?: string;
reason: string;
}
/**
* Entity Orchestrator Class
* Manages complex multi-step entity creation workflows
*/
export declare class EntityOrchestrator {
private apiHelper;
private entityRouter;
private logger;
private entityReferenceCache;
private autoDecisions;
private cacheManager;
private mcpTools?;
constructor(apiHelper: OptimizelyAPIHelper, cacheManager: any, storage: any, existingEntityRouter?: EntityRouter);
/**
* Get or create OptimizelyMCPTools instance
* @returns OptimizelyMCPTools instance
*/
private getMCPTools;
/**
* Helper method to detect "Everyone" audience references
* "Everyone" is a special virtual audience that doesn't exist in the database
*/
private isEveryoneAudience;
/**
* Create a feature flag with optional variables and A/B test
* @param projectId - Project ID
* @param processedTemplate - Processed template data
* @returns Orchestration result
*/
createFlagWithABTest(projectId: string, processedTemplate: ProcessedTemplate): Promise<OrchestrationResult>;
/**
* Create a web experiment with page targeting
* @param projectId - Project ID
* @param processedTemplate - Processed template data
* @returns Orchestration result
*/
createWebExperimentWithPage(projectId: string, processedTemplate: ProcessedTemplate): Promise<OrchestrationResult>;
/**
* Create an audience with complex conditions
* @param projectId - Project ID
* @param processedTemplate - Processed template data
* @returns Orchestration result
*/
createAudienceWithConditions(projectId: string, processedTemplate: ProcessedTemplate): Promise<OrchestrationResult>;
/**
* Execute a single orchestration step directly (bypasses MCP transformation layer)
* Used by StepExecutor to avoid broken manageEntityLifecycle transformations
*/
executeDirectStep(projectId: string, stepConfig: {
stepName: string;
entityType: string;
operation: string;
data: any;
dependencies?: string[];
optional?: boolean;
}, existingState?: any): Promise<any>;
/**
* Execute an orchestration plan with dependency resolution and rollback
* @param projectId - Project ID
* @param steps - Array of orchestration steps
* @returns Orchestration result
*/
private executeOrchestration;
/**
* Resolve template variables like ${stepName.field} in data
* @param data - Data object with potential template variables
* @param entityIdMap - Mapping of step names to entity IDs
* @param createdEntities - Array of created entities with full results
* @returns Resolved data object
*/
private resolveTemplateVariables;
/**
* Transform variable values to Feature Experimentation API format
* @param variableValues - Object with variable key-value pairs
* @returns Transformed object where each value is wrapped in {value: originalValue}
*/
private transformVariableValues;
/**
* Process variation actions to ensure proper structure for web experiments
* @param actions - Array of actions for the variation
* @param templateData - Template data containing page information
* @returns Processed actions array
*/
private processVariationActions;
/**
* Ensure page_id is an integer (not a string)
* @param pageId - The page ID to convert
* @returns Integer page ID or the original value if it's a template variable
*/
private ensureIntegerPageId;
/**
* Rollback created entities in reverse order
* @param projectId - Project ID
* @param createdEntities - Array of created entities to rollback
* @returns Rollback result
*/
private rollbackCreatedEntities;
/**
* Check if a template requires orchestration (has multiple entity types)
* @param processedTemplate - Processed template data
* @returns True if orchestration is needed
*/
static requiresOrchestration(processedTemplate: ProcessedTemplate): boolean;
/**
* Get the appropriate orchestration method based on template type
* @param entityType - Primary entity type being created
* @param processedTemplate - Processed template data
* @returns Method name for orchestration
*/
static getOrchestrationMethod(entityType: string, processedTemplate: ProcessedTemplate): string | null;
/**
* Determines if an entity type should be checked for existence before creation
* @param entityType - The entity type to check
* @returns True if entity should be checked for existence
*/
private shouldCheckForExistence;
/**
* Formats variation key to display name
* @param key - Variation key (e.g., "control", "variation_1")
* @returns Formatted display name (e.g., "Control", "Variation 1")
*/
private formatVariationName;
/**
* Extracts entity reference information from entity data
* @param entityData - The entity data to extract reference from
* @param entityType - The type of entity to extract reference for
* @returns Reference object for entity lookup with appropriate fields
*/
private extractEntityReference;
/**
* Resolves an entity reference to check if it exists
* @param entityType - Type of entity to resolve
* @param reference - Entity reference (key, name, or object with criteria)
* @param projectId - Project ID for project-scoped entities
* @returns Object indicating if entity exists and the entity data if found
*/
private resolveEntityReference;
/**
* Process a template with entity references before orchestration
* Resolves {EXISTING}, {FIND_OR_CREATE}, and {CREATE_NEW} placeholders
* @param template - Template containing entity references
* @param projectId - Project ID for entity lookups
* @returns Processed template with resolved references
*/
processTemplateWithReferences(template: any, projectId: string): Promise<{
processedTemplate: any;
referenceErrors: string[];
}>;
/**
* Clear the entity reference cache
* Should be called at the start of each orchestration session
*/
clearReferenceCache(): void;
/**
* Resolve attribute references in audience conditions
* @param conditions - Audience conditions that may contain attribute references
* @param projectId - Project ID for attribute lookup
* @returns Conditions with resolved attribute IDs
*/
private resolveAttributeReferences;
/**
* Resolve all refs in a model-friendly template
* @param data - The filled template data containing refs
* @param projectId - Project ID for context
* @returns Resolved data with refs replaced by actual IDs/keys
*/
resolveModelFriendlyRefs(data: any, projectId: string): Promise<any>;
/**
* Resolve a single ref helper
* @param ref - The ref object containing lookup/creation info
* @param projectId - Project ID for context
* @returns The resolved entity ID or created entity data
*/
private resolveRef;
/**
* Lookup an entity using ref criteria
* @param entityType - Type of entity to lookup
* @param ref - Ref containing lookup criteria
* @param projectId - Project ID
* @returns Found entity or null
*/
private lookupEntity;
/**
* Create entity from ref template
* @param entityType - Type of entity to create
* @param template - Mini template for creation
* @param projectId - Project ID
* @returns Created entity
*/
private createFromRefTemplate;
/**
* Infer entity type from ref context
* This would need to be enhanced to use path context
* @param ref - The ref object
* @returns Inferred entity type
*/
private inferEntityTypeFromRef;
/**
* Set value at a nested path in an object
* @param obj - Object to modify
* @param path - Dot-notation path (e.g., "ab_test.metrics[0]")
* @param value - Value to set
*/
private setValueAtPath;
/**
* Build enhanced orchestration summary for better AI agent understanding
* @param result - Basic orchestration result
* @param templateData - Original template data
* @param projectId - Project ID
* @returns Enhanced orchestration result with detailed summary
*/
private buildEnhancedOrchestrationResult;
/**
* Track an auto decision made by the orchestrator
* @param field - Field that was auto-filled
* @param value - Value that was set
* @param reason - Reason for the auto-fill
*/
private trackAutoDecision;
}
//# sourceMappingURL=EntityOrchestrator.d.ts.map