Skip to main content
Glama
composition-manager.ts6.67 kB
/** * EuConquisto Composer Management * * High-level composition operations using the HTTP API client. * Handles natural language processing and widget creation. */ import { EuConquistoAPIClient, CompositionData, CompositionWidget, CompositionMetadata } from './api-client.js'; export interface CompositionRequest { title: string; description?: string; content: string; widgets?: Array<{ type: 'text' | 'header' | 'list' | 'image'; content: string; properties?: Record<string, any>; }>; } export interface CompositionResult { success: boolean; compositionUID?: string; message: string; data?: any; error?: string; } export class CompositionManager { private apiClient: EuConquistoAPIClient; constructor() { this.apiClient = new EuConquistoAPIClient(); } /** * Create a new composition from natural language description */ async createFromDescription(request: CompositionRequest): Promise<CompositionResult> { try { // Create basic composition structure const composition = this.apiClient.createBasicComposition( request.title, request.description ); // Process content and add widgets if (request.widgets && request.widgets.length > 0) { // Use explicitly provided widgets for (const widget of request.widgets) { const compositionWidget = this.createWidgetFromSpec(widget); composition.structure.push(compositionWidget); } } else { // Parse natural language content into widgets const widgets = this.parseContentIntoWidgets(request.content); composition.structure.push(...widgets); } // Create via API const result = await this.apiClient.createComposition(composition); if (result.success) { return { success: true, compositionUID: result.data?.uid || 'unknown', message: `Composition "${request.title}" created successfully`, data: result.data }; } else { return { success: false, message: 'Failed to create composition', error: result.error }; } } catch (error) { return { success: false, message: 'Error creating composition', error: error instanceof Error ? error.message : 'Unknown error' }; } } /** * Update composition metadata */ async updateMetadata(uid: string, metadata: Partial<CompositionMetadata>): Promise<CompositionResult> { try { // For now, we'll need to get the existing composition and update it // This is a simplified version - in production, you'd want to fetch existing data first const basicComposition = this.apiClient.createBasicComposition( metadata.title || "Updated Composition", metadata.description ); if (metadata.tags) { basicComposition.metadata.tags = metadata.tags; } const result = await this.apiClient.updateComposition(uid, basicComposition); if (result.success) { return { success: true, compositionUID: uid, message: 'Composition metadata updated successfully', data: result.data }; } else { return { success: false, message: 'Failed to update composition metadata', error: result.error }; } } catch (error) { return { success: false, message: 'Error updating composition metadata', error: error instanceof Error ? error.message : 'Unknown error' }; } } /** * Test API connection */ async testConnection(): Promise<CompositionResult> { try { const result = await this.apiClient.testConnection(); return { success: result.success, message: result.success ? 'API connection successful' : 'API connection failed', data: result.data, error: result.error }; } catch (error) { return { success: false, message: 'Connection test failed', error: error instanceof Error ? error.message : 'Unknown error' }; } } /** * Parse natural language content into widgets */ private parseContentIntoWidgets(content: string): CompositionWidget[] { const widgets: CompositionWidget[] = []; // Simple parsing logic - can be enhanced with more sophisticated NLP const lines = content.split('\n').filter(line => line.trim()); for (const line of lines) { const trimmed = line.trim(); if (trimmed.startsWith('#')) { // Header widget const headerText = trimmed.replace(/^#+\s*/, ''); widgets.push(this.apiClient.addHeaderWidget(headerText)); } else if (trimmed.length > 0) { // Text widget widgets.push(this.apiClient.addTextWidget(trimmed)); } } // If no widgets created, add the entire content as a single text widget if (widgets.length === 0) { widgets.push(this.apiClient.addTextWidget(content)); } return widgets; } /** * Create widget from specification */ private createWidgetFromSpec(spec: { type: 'text' | 'header' | 'list' | 'image'; content: string; properties?: Record<string, any>; }): CompositionWidget { switch (spec.type) { case 'header': return this.apiClient.addHeaderWidget(spec.content); case 'text': return this.apiClient.addTextWidget(spec.content); case 'list': // Simple list implementation const listContent = `<ul>${spec.content.split('\n') .filter(item => item.trim()) .map(item => `<li>${item.trim()}</li>`) .join('')}</ul>`; return { id: this.generateUID(), type: "list-1", content: listContent, background_color: "#FFFFFF", padding_top: 0, padding_bottom: 0 }; case 'image': return { id: this.generateUID(), type: "image-1", content: spec.content, // Image URL or description background_color: "#FFFFFF", padding_top: 0, padding_bottom: 0, ...spec.properties }; default: return this.apiClient.addTextWidget(spec.content); } } /** * Generate a simple UID */ private generateUID(): string { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { const r = Math.random() * 16 | 0; const v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rkm097git/euconquisto-composer-mcp-poc'

If you have feedback or need assistance with the MCP directory API, please join our Discord server