import {DiagramEntity, DiagramEntityType, DiagramTemplates} from "../../diagram/types/diagramEntity"; import { COLOR_NAME_TO_HEX, ConnectEntitiesParams, CreateEntityParams, ModifyEntityParams, RemoveEntityParams, SHAPE_TO_TEMPLATE, ToolResult } from "../types/chatTypes"; import {v4 as uuidv4} from 'uuid'; function resolveColor(color?: string): string { if (!color) return '#0000ff'; const lower = color.toLowerCase(); if (COLOR_NAME_TO_HEX[lower]) { return COLOR_NAME_TO_HEX[lower]; } if (color.startsWith('#')) { return color; } return '#0000ff'; } export function createEntity(params: CreateEntityParams): ToolResult { const id = 'id' + uuidv4(); const template = SHAPE_TO_TEMPLATE[params.shape]; const color = resolveColor(params.color); const position = params.position || {x: 0, y: 1.5, z: 2}; const entity: DiagramEntity = { id, template, type: DiagramEntityType.ENTITY, color, text: params.label || '', position, rotation: {x: 0, y: Math.PI, z: 0}, scale: {x: 0.1, y: 0.1, z: 0.1}, }; const event = new CustomEvent('chatCreateEntity', { detail: {entity}, bubbles: true }); document.dispatchEvent(event); return { toolName: 'create_entity', success: true, message: `Created ${params.shape}${params.label ? ` labeled "${params.label}"` : ''} at position (${position.x.toFixed(1)}, ${position.y.toFixed(1)}, ${position.z.toFixed(1)})`, entityId: id }; } export function connectEntities(params: ConnectEntitiesParams): ToolResult { const id = 'id' + uuidv4(); const color = resolveColor(params.color); const entity: DiagramEntity = { id, template: DiagramTemplates.CONNECTION, type: DiagramEntityType.ENTITY, color, from: params.from, to: params.to, }; const event = new CustomEvent('chatCreateEntity', { detail: {entity}, bubbles: true }); document.dispatchEvent(event); return { toolName: 'connect_entities', success: true, message: `Connected "${params.from}" to "${params.to}"`, entityId: id }; } export function removeEntity(params: RemoveEntityParams): ToolResult { const event = new CustomEvent('chatRemoveEntity', { detail: {target: params.target}, bubbles: true }); document.dispatchEvent(event); return { toolName: 'remove_entity', success: true, message: `Removed entity "${params.target}"` }; } export function modifyEntity(params: ModifyEntityParams): ToolResult { const updates: Partial = {}; if (params.color) { updates.color = resolveColor(params.color); } if (params.label !== undefined) { updates.text = params.label; } if (params.position) { updates.position = params.position; } const event = new CustomEvent('chatModifyEntity', { detail: {target: params.target, updates}, bubbles: true }); document.dispatchEvent(event); return { toolName: 'modify_entity', success: true, message: `Modified entity "${params.target}"` }; } export function listEntities(): Promise { return new Promise((resolve) => { const responseHandler = (e: CustomEvent) => { document.removeEventListener('chatListEntitiesResponse', responseHandler as EventListener); const entities = e.detail.entities as Array<{ id: string; template: string; text: string; position: { x: number; y: number; z: number } }>; if (entities.length === 0) { resolve({ toolName: 'list_entities', success: true, message: 'The diagram is empty.' }); return; } const list = entities.map(e => { const shape = e.template.replace('#', '').replace('-template', ''); return `- ${e.text || '(no label)'} (${shape}) at (${e.position?.x?.toFixed(1) || 0}, ${e.position?.y?.toFixed(1) || 0}, ${e.position?.z?.toFixed(1) || 0}) [id: ${e.id}]`; }).join('\n'); resolve({ toolName: 'list_entities', success: true, message: `Current entities in the diagram:\n${list}` }); }; document.addEventListener('chatListEntitiesResponse', responseHandler as EventListener); const event = new CustomEvent('chatListEntities', {bubbles: true}); document.dispatchEvent(event); setTimeout(() => { document.removeEventListener('chatListEntitiesResponse', responseHandler as EventListener); resolve({ toolName: 'list_entities', success: false, message: 'Failed to list entities (timeout)' }); }, 5000); }); }