170 lines
5.0 KiB
TypeScript
170 lines
5.0 KiB
TypeScript
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<DiagramEntity> = {};
|
|
|
|
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<ToolResult> {
|
|
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);
|
|
});
|
|
}
|