File size: 2,770 Bytes
d9494a5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import {
  type ExtendedFileUIPart,
  type ExtendedUIMessagePart,
} from 'twenty-shared/ai';

import { type AgentMessagePartEntity } from 'src/engine/metadata-modules/ai/ai-agent-execution/entities/agent-message-part.entity';

// Maps TypeORM entity fields to UI message parts.
// A parallel mapping for GraphQL DTOs exists in the frontend at:
// packages/twenty-front/src/modules/ai/utils/mapDBPartToUIMessagePart.ts

export const mapDBPartToUIMessagePart = (
  part: AgentMessagePartEntity,
): ExtendedUIMessagePart | null => {
  switch (part.type) {
    case 'text':
      return {
        type: 'text',
        text: part.textContent ?? '',
      };
    case 'reasoning':
      return {
        type: 'reasoning',
        text: part.reasoningContent ?? '',
        state: (part.state as 'streaming' | 'done') ?? 'done',
        providerMetadata: part.providerMetadata ?? undefined,
      };
    case 'file':
      return {
        type: 'file',
        mediaType: part.file?.mimeType ?? 'application/octet-stream',
        filename: part.fileFilename ?? '',
        url: '',
        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: 'step-start',
      };
    case 'data-routing-status':
      return null;
    default: {
      const isStaticToolPart =
        part.type.startsWith('tool-') && part.toolCallId !== null;
      const isDynamicToolPart =
        part.type === 'dynamic-tool' && part.toolCallId !== null;

      if (isStaticToolPart || isDynamicToolPart) {
        return {
          type: part.type,
          ...(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;
      }

      return null;
    }
  }
};