import { type ReasoningUIPart } from 'ai'; import { type ExtendedFileUIPart, type ExtendedUIMessagePart, } from 'twenty-shared/ai'; import { type AgentMessagePart } from '~/generated-metadata/graphql'; // Maps GraphQL DTO fields to UI message parts. // A parallel mapping for TypeORM entities exists in the server at: // packages/twenty-server/src/engine/metadata-modules/ai/ai-agent-execution/utils/mapDBPartsToUIMessageParts.ts export const mapDBPartToUIMessagePart = ( part: AgentMessagePart, ): ExtendedUIMessagePart => { switch (part.type) { case 'text': return { type: 'text', text: part.textContent!, }; case 'reasoning': return { type: 'reasoning', text: part.reasoningContent!, state: part.state as ReasoningUIPart['state'], providerMetadata: part.providerMetadata ?? undefined, }; case 'file': return { type: 'file', mediaType: part.fileMediaType!, filename: part.fileFilename!, url: part.fileUrl!, fileId: part.fileId!, } as ExtendedFileUIPart; case 'source-url': return { type: 'source-url', sourceId: part.sourceUrlSourceId!, url: part.sourceUrlUrl!, title: part.sourceUrlTitle!, providerMetadata: part.providerMetadata ?? undefined, }; case 'source-document': return { type: 'source-document', sourceId: part.sourceDocumentSourceId!, mediaType: part.sourceDocumentMediaType!, title: part.sourceDocumentTitle!, filename: part.sourceDocumentFilename!, providerMetadata: part.providerMetadata ?? undefined, }; case 'step-start': return { type: part.type, }; case 'data-routing-status': return { type: part.type, data: { text: part.textContent!, state: part.state!, }, }; default: { const isStaticToolPart = part.type.startsWith('tool-'); const isDynamicToolPart = part.type === 'dynamic-tool'; if (isStaticToolPart || isDynamicToolPart) { return { type: part.type as `tool-${string}` | 'dynamic-tool', ...(isDynamicToolPart && { toolName: part.toolName ?? '' }), toolCallId: part.toolCallId!, input: part.toolInput ?? {}, output: part.toolOutput, errorText: part.errorMessage!, state: part.state, ...(part.providerExecuted != null && { providerExecuted: part.providerExecuted, }), ...(part.providerMetadata != null && { callProviderMetadata: part.providerMetadata, }), } as ExtendedUIMessagePart; } } throw new Error(`Unsupported part type: ${part.type}`); } };