{
  "version": 3,
  "sources": ["../../../../src/logic-functions/session-started.ts", "twenty-sdk-define-stub:__twenty-sdk-define-stub__", "../../../../src/constants/universal-identifiers.ts", "../../../../src/objects/session.object.ts"],
  "sourcesContent": ["import { CoreApiClient } from 'twenty-client-sdk/core';\nimport { defineLogicFunction, RoutePayload } from 'twenty-sdk/define';\n\nimport { SESSION_STARTED_LF } from 'src/constants/universal-identifiers';\nimport { SessionChannel } from 'src/objects/session.object';\n\n// Talqui -> Twenty session-started receiver. POST /s/talqui/session-started.\n//\n// Called by plugin-crms when a Talqui session starts. The wire payload is\n// session-based (`{ session, personID }`); the session object that stores it\n// is surfaced to the user as \"Conversation\", keyed by externalId (= the Talqui\n// sessionID). Replays update the same row instead of duplicating.\n//\n// Route namespace: every HTTP route of this app lives under /talqui/<path>\n// \u2014 /s/ is shared by all installed apps, the prefix identifies ours.\n\ntype SessionStartedBody = {\n  session?: {\n    sessionID?: string;\n    title?: string;\n    channel?: string;\n    startedAt?: string;\n    url?: string;\n    // Attribution (CTWA referral), all optional \u2014 only paid Click-to-WhatsApp\n    // conversations carry them.\n    utmSource?: string;\n    utmMedium?: string;\n    utmContent?: string;\n    utmCampaign?: string;\n    metaAdId?: string;\n    ctwaClid?: string;\n    talquiLeadId?: string;\n    // Opportunity (Twenty record id) this conversation belongs to \u2014 the events\n    // bridge resolves it from the tlid upsert. FK `opportunityId` on the\n    // Conversation (1 opportunity -> N conversations).\n    opportunityId?: string;\n  };\n  personID?: string;\n};\n\ntype HandlerResult = {\n  ok: true;\n  processed: boolean;\n  reason?: string;\n  recordId?: string;\n};\n\nconst KNOWN_CHANNELS = new Set<string>(Object.values(SessionChannel));\n\nexport const handler = async (\n  payload: RoutePayload<SessionStartedBody>,\n): Promise<HandlerResult> => {\n  const session = payload.body?.session;\n  const sessionID = session?.sessionID?.trim();\n  const channel = session?.channel;\n  const startedAt = session?.startedAt;\n\n  if (!sessionID || !channel || !startedAt) {\n    console.warn(\n      `session-started: invalid payload (sessionID=${sessionID ?? 'missing'})`,\n    );\n    return { ok: true, processed: false, reason: 'invalid_payload' };\n  }\n\n  const personID = payload.body?.personID;\n  const client = new CoreApiClient() as any;\n\n  // Non-exclusive company auto-link: when the contact already belongs to a\n  // company, mirror that link onto the Conversation so a company's conversations\n  // are discoverable automatically. Best-effort \u2014 a missing person, no company,\n  // or a lookup error just creates the Conversation without the link.\n  let companyId: string | undefined;\n  if (personID) {\n    const personLookup = await client\n      .query({ person: { __args: { filter: { id: { eq: personID } } }, companyId: true } })\n      .catch(() => null);\n    const resolvedCompanyId = personLookup?.person?.companyId;\n    if (resolvedCompanyId) companyId = String(resolvedCompanyId);\n  }\n\n  // Attribution: pass through only the fields present (keeps replays/updates\n  // partial \u2014 an update never blanks an existing value with undefined).\n  const attribution: Record<string, unknown> = {};\n  for (const key of ['utmSource', 'utmMedium', 'utmContent', 'utmCampaign', 'metaAdId', 'ctwaClid', 'talquiLeadId'] as const) {\n    const value = session[key];\n    if (value !== undefined && value !== null && value !== '') attribution[key] = value;\n  }\n\n  const data: Record<string, unknown> = {\n    name: session.title ?? `Conversation ${sessionID}`,\n    channel: KNOWN_CHANNELS.has(channel) ? channel : SessionChannel.OTHER,\n    startedAt,\n    externalId: sessionID,\n    ...(session.url\n      ? {\n          url: {\n            primaryLinkUrl: session.url,\n            primaryLinkLabel: 'Open in Talqui',\n          },\n        }\n      : {}),\n    ...(personID ? { contactId: personID } : {}),\n    ...(companyId ? { companyId } : {}),\n    // Link the conversation to its opportunity (FK on the Conversation side).\n    ...(session.opportunityId ? { opportunityId: session.opportunityId } : {}),\n    ...attribution,\n  };\n\n  const lookup = await client\n    .query({\n      session: {\n        __args: { filter: { externalId: { eq: sessionID } } },\n        id: true,\n      },\n    })\n    .catch(() => null);\n  const existingId: string | undefined = lookup?.session?.id;\n\n  try {\n    if (existingId) {\n      await client.mutation({\n        updateSession: {\n          __args: { id: existingId, data },\n          id: true,\n        },\n      });\n      console.log(`session-started: replayed sessionID=${sessionID} recordId=${existingId}`);\n      return { ok: true, processed: true, recordId: existingId };\n    }\n\n    const created = await client.mutation({\n      createSession: {\n        __args: { data },\n        id: true,\n      },\n    });\n    const recordId: string = created.createSession.id;\n    console.log(`session-started: created sessionID=${sessionID} recordId=${recordId}`);\n    return { ok: true, processed: true, recordId };\n  } catch (err) {\n    console.error(\n      `session-started: upsert failed sessionID=${sessionID}: ${\n        err instanceof Error ? err.message : String(err)\n      }`,\n    );\n    return { ok: true, processed: false, reason: 'upsert_failed' };\n  }\n};\n\nexport default defineLogicFunction({\n  universalIdentifier: SESSION_STARTED_LF,\n  name: 'session-started',\n  description:\n    'Receives session-started signals from plugin-crms and upserts the matching Conversation by externalId (= Talqui sessionID).',\n  timeoutSeconds: 30,\n  handler,\n  httpRouteTriggerSettings: {\n    path: '/talqui/session-started',\n    httpMethod: 'POST',\n    isAuthRequired: true,\n  },\n});\n", "\n// Auto-generated stub for twenty-sdk/define injected by the SDK CLI build.\n// Real implementations would pull in zod, twenty-shared and ~1MB of code; at\n// runtime only `default.config.handler` is consumed, so tiny no-ops suffice.\nconst __defineFactoryStub = (config) => ({\n  success: true,\n  config,\n  errors: [],\n});\n\nconst __anyHandler = {\n  get(_target, prop) {\n    if (prop === '__esModule') return true;\n    if (prop === Symbol.toPrimitive) return () => '';\n    if (typeof prop === 'symbol') return undefined;\n    return new Proxy(() => undefined, __anyHandler);\n  },\n  apply() {\n    return new Proxy(() => undefined, __anyHandler);\n  },\n};\nconst __anyStub = new Proxy(() => undefined, __anyHandler);\n\nexport const createValidationResult = __defineFactoryStub;\nexport const defineAgent = __defineFactoryStub;\nexport const defineApplication = __defineFactoryStub;\nexport const defineApplicationRole = __defineFactoryStub;\nexport const defineCommandMenuItem = __defineFactoryStub;\nexport const defineConnectionProvider = __defineFactoryStub;\nexport const defineField = __defineFactoryStub;\nexport const defineFrontComponent = __defineFactoryStub;\nexport const defineIndex = __defineFactoryStub;\nexport const defineLogicFunction = __defineFactoryStub;\nexport const defineNavigationMenuItem = __defineFactoryStub;\nexport const defineObject = __defineFactoryStub;\nexport const definePageLayout = __defineFactoryStub;\nexport const definePageLayoutTab = __defineFactoryStub;\nexport const definePermissionFlag = __defineFactoryStub;\nexport const definePostInstallLogicFunction = __defineFactoryStub;\nexport const definePreInstallLogicFunction = __defineFactoryStub;\nexport const defineRole = __defineFactoryStub;\nexport const defineSkill = __defineFactoryStub;\nexport const defineView = __defineFactoryStub;\nexport const defineViewField = __defineFactoryStub;\nexport const AggregateOperations = __anyStub;\nexport const DateDisplayFormat = __anyStub;\nexport const FieldMetadataSettingsOnClickAction = __anyStub;\nexport const FieldType = __anyStub;\nexport const HTTPMethod = __anyStub;\nexport const NavigationMenuItemType = __anyStub;\nexport const NumberDataType = __anyStub;\nexport const ObjectRecordGroupByDateGranularity = __anyStub;\nexport const OnDeleteAction = __anyStub;\nexport const PageLayoutTabLayoutMode = __anyStub;\nexport const PageLayoutType = __anyStub;\nexport const RelationType = __anyStub;\nexport const RowLevelPermissionPredicateGroupLogicalOperator = __anyStub;\nexport const RowLevelPermissionPredicateOperand = __anyStub;\nexport const STANDARD_OBJECT = __anyStub;\nexport const STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS = __anyStub;\nexport const STANDARD_PAGE_LAYOUT = __anyStub;\nexport const STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS = __anyStub;\nexport const SystemPermissionFlag = __anyStub;\nexport const ViewCalendarLayout = __anyStub;\nexport const ViewFilterGroupLogicalOperator = __anyStub;\nexport const ViewFilterOperand = __anyStub;\nexport const ViewKey = __anyStub;\nexport const ViewOpenRecordIn = __anyStub;\nexport const ViewSortDirection = __anyStub;\nexport const ViewType = __anyStub;\nexport const ViewVisibility = __anyStub;\nexport const canAccessFullAdminPanel = __anyStub;\nexport const canImpersonate = __anyStub;\nexport const every = __anyStub;\nexport const everyDefined = __anyStub;\nexport const everyEquals = __anyStub;\nexport const favoriteRecordIds = __anyStub;\nexport const featureFlags = __anyStub;\nexport const generateDefaultFieldUniversalIdentifier = __anyStub;\nexport const hasAnySoftDeleteFilterOnView = __anyStub;\nexport const includes = __anyStub;\nexport const includesEvery = __anyStub;\nexport const isDashboardPageLayoutInEditMode = __anyStub;\nexport const isDefined = __anyStub;\nexport const isInSidePanel = __anyStub;\nexport const isLayoutCustomizationModeEnabled = __anyStub;\nexport const isNonEmptyString = __anyStub;\nexport const isSelectAll = __anyStub;\nexport const none = __anyStub;\nexport const noneDefined = __anyStub;\nexport const noneEquals = __anyStub;\nexport const numberOfSelectedRecords = __anyStub;\nexport const objectMetadataItem = __anyStub;\nexport const objectMetadataLabel = __anyStub;\nexport const objectPermissions = __anyStub;\nexport const pageType = __anyStub;\nexport const selectedRecords = __anyStub;\nexport const some = __anyStub;\nexport const someDefined = __anyStub;\nexport const someEquals = __anyStub;\nexport const someNonEmptyString = __anyStub;\nexport const targetObjectReadPermissions = __anyStub;\nexport const targetObjectWritePermissions = __anyStub;\nexport const validateFields = __anyStub;\n", "export const APP_DISPLAY_NAME = 'Talqui Chat';\nexport const APP_DESCRIPTION = 'AI-powered chat for Webchat, WhatsApp and Instagram integrated to your CRM';\nexport const APPLICATION_UNIVERSAL_IDENTIFIER = '7880eb3d-e2cd-4396-a9ed-159b1eecb2fd';\nexport const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER = 'ca41b3b3-bd0d-431c-bfa2-dfc110719b98';\nexport const MAIN_PAGE_FRONT_COMPONENT_UNIVERSAL_IDENTIFIER =\n  'a953a135-ed35-4c4d-81df-bbcc492c93a1';\nexport const MAIN_PAGE_LAYOUT_UNIVERSAL_IDENTIFIER = 'd7d70821-9c3c-43ee-8434-b7d043c4dc13';\nexport const MAIN_PAGE_LAYOUT_TAB_UNIVERSAL_IDENTIFIER = '56cfc3dd-a891-45a8-a65d-296dcd5911aa';\nexport const MAIN_PAGE_WIDGET_UNIVERSAL_IDENTIFIER = '790e051c-7c53-48fc-a87f-425caf118b94';\nexport const MAIN_PAGE_NAVIGATION_MENU_ITEM_UNIVERSAL_IDENTIFIER =\n  '9f21b9d7-93d9-45d5-a58d-ee03e745a3f9';\n\n// Session object + scalar fields (labelled \"Conversation\" in the UI).\n// NOTE: universalIdentifiers are frozen \u2014 only the const names changed.\nexport const SESSION_UNIVERSAL_IDENTIFIER = 'ce892978-2336-4d31-a146-85872d516fce';\nexport const SESSION_NAME_FIELD = '9eb6fdec-ea9a-4351-bd2d-01c38482095d';\nexport const SESSION_CHANNEL_FIELD = 'e1e4fb47-53de-42c3-925c-e5b07dfb2f89';\nexport const SESSION_STARTED_AT_FIELD = '8a33e25f-1dd8-490a-8ace-2fb44d861242';\nexport const SESSION_ENDED_AT_FIELD = '4f506405-2d82-465b-8837-6e4451bba7fa';\nexport const SESSION_DURATION_SEC_FIELD = '002aa75b-b157-4958-9e7f-cb306dfd15fd';\nexport const SESSION_URL_FIELD = '8a33b10d-5fa2-4089-8dc3-8c6a7af6b9fb';\nexport const SESSION_EXTERNAL_ID_FIELD = 'd1e630df-82b5-4098-9f3c-220325d18b94';\nexport const SESSION_SUMMARY_FIELD = '769554b2-6dd6-4150-91c5-2179a506ca11';\nexport const SESSION_CSAT_SCORE_FIELD = 'a887b5b7-755b-4dce-b620-0d3af6e553f6';\nexport const SESSION_MOTIVE_FIELD = '4193c755-ef60-425e-90ef-1c754e26c1d3';\n\n// Relations: session <-> standard objects\nexport const SESSION_PERSON_FIELD = '7951fe9d-9e1e-40b0-8a01-0320050bc2c6';\nexport const PERSON_SESSIONS_FIELD = '2d7a0882-1c70-4563-a70a-ef75f12aec89';\nexport const SESSION_COMPANY_FIELD = '08cba9e4-ca7a-4446-94f2-9d9077c55995';\nexport const COMPANY_SESSIONS_FIELD = 'b4b50b67-9949-4c86-9903-872f6fd22e6e';\n// Opportunity <-> Conversation, INVERTED (2026-07-04): 1 Opportunity -> N\n// Conversations. The FK now lives on the Conversation (session.opportunity,\n// joinColumn `opportunityId`); the opportunity exposes the O2M `sessions`. The\n// previous pair (FK on Opportunity, 1 conversation max) is retired \u2014 its old\n// universalIdentifiers are dropped by the sync, the new ones created.\nexport const OPPORTUNITY_SESSIONS_FIELD = '6655c67b-8fc9-47c8-a304-4d4a23f66591';\nexport const SESSION_OPPORTUNITY_FIELD = 'aadd5275-e156-4a3e-a9fc-673064a8ee0f';\n\n// Scalar field added to the standard Opportunity object: the Talqui lead id\n// (sessionMeta.tlID), the natural key the events bridge upserts opportunities by.\n// Field-level isUnique enforces one opportunity per tlid (a standalone index on a\n// standard object is rejected by the app sync).\nexport const OPPORTUNITY_TALQUI_LEAD_ID_FIELD = 'ed405d4a-9de1-490f-beb6-f3e9550ce404';\n\n// Attribution added to the app-owned Conversation (session) object. Because the\n// object and its fields ship with the app, every installer auto-provisions them\n// \u2014 no manual field creation, and the events bridge writes them via the\n// session-started logic function (no custom-field validation risk). Populated\n// from the CTWA referral (session.sessionMeta.referral*): utm* are the base UTM\n// slots (source=instagram, medium=paid_social; campaign deferred to the CAPI\n// phase), metaAdId is the ad id, ctwaClid is the Meta click id (CAPI key), and\n// talquiLeadId mirrors the opportunity key when the session carries one.\nexport const SESSION_UTM_SOURCE_FIELD = 'b52bd069-bf24-439d-a44a-89e30203961d';\nexport const SESSION_UTM_MEDIUM_FIELD = '5726e06c-bd05-470f-b557-6b0164640e03';\nexport const SESSION_UTM_CONTENT_FIELD = 'bd8cc3e5-8a21-4492-bfc4-67d0ec26d1be';\nexport const SESSION_UTM_CAMPAIGN_FIELD = 'cd05059c-f12e-497d-8104-f8b4073c91b3';\nexport const SESSION_META_AD_ID_FIELD = '3098d356-7374-4f95-bb9b-3c715684a2b5';\nexport const SESSION_CTWA_CLID_FIELD = '1bab2e39-1166-449d-ba6f-99bc48edee29';\nexport const SESSION_TALQUI_LEAD_ID_FIELD = 'e742d1d0-69ba-4303-8c62-994686c4cdf5';\n\n// SessionNote object + fields + relation pair\nexport const SESSION_NOTE_UNIVERSAL_IDENTIFIER = '66434c3c-6581-4777-9c6a-64fb0bbc3feb';\nexport const SESSION_NOTE_NAME_FIELD = 'e9188436-664f-4862-aced-4e747f3aee31';\nexport const SESSION_NOTE_CREATED_AT_FIELD = 'b91e5608-871f-4f52-b3e0-a40afd96bc58';\nexport const SESSION_NOTE_BODY_FIELD = 'c4599c9f-49b5-4438-adc4-8d5463f146ac';\nexport const SESSION_NOTE_SESSION_FIELD = '866ffb7a-dfbf-416e-8423-b0e3479c34d2';\nexport const SESSION_NOTES_FIELD = '7cdd103c-9c5d-4963-b6fe-3100e87c4963';\n\n// Navigation + views\nexport const ALL_SESSIONS_VIEW = 'd730029c-e0b0-4e12-8212-394ebbafad46';\nexport const SESSIONS_NAV_MENU_ITEM = '0cefb558-0031-4d6e-b2d6-1e3e879ae10b';\n\n// Logic functions (session signals bridge)\nexport const SESSION_STARTED_LF = '040ff442-79d4-4c4a-9af5-5f3c64058776';\nexport const SESSION_CLOSED_LF = '7a4d6297-5b70-4fea-ac71-706c247472f2';\nexport const SESSION_SUMMARIZED_LF = '995758ca-84dd-41ca-a284-690acade82c4';\n// DB-event LF: links an ad-hoc (widget/manual) opportunity to the contact's\n// most-recent free conversation on create.\nexport const OPPORTUNITY_CREATED_LF = '7b7be604-8f33-420f-9332-fe0e54fdf611';\n\n// \"Conversations\" tab on Person/Company/Opportunity record pages.\nexport const PERSON_RECORD_PAGE_LAYOUT = '20202020-a102-4002-8002-ae0a1ea11002';\nexport const COMPANY_RECORD_PAGE_LAYOUT = '20202020-a101-4001-8001-c0aba11c0001';\nexport const OPPORTUNITY_RECORD_PAGE_LAYOUT = '20202020-a103-4003-8003-0aa0b1ca1003';\n\n// Each object gets a page-layout-tab + a FIELD widget bound to the relation.\nexport const PERSON_CONVERSATIONS_TAB = 'c746f718-a089-4d74-8568-c7a1d091e322';\nexport const PERSON_CONVERSATIONS_WIDGET = '9c3914ca-5e11-430e-b5e0-7bdfcb61915b';\nexport const COMPANY_CONVERSATIONS_TAB = 'a406030c-abc9-4495-898a-45fc1910f594';\nexport const COMPANY_CONVERSATIONS_WIDGET = 'df424ee9-2c7d-4072-8ba6-20cc1e9cc099';\nexport const OPPORTUNITY_CONVERSATIONS_TAB = '97bacaa2-c8c6-48b4-8223-501ee41bce6c';\nexport const OPPORTUNITY_CONVERSATIONS_WIDGET = '6c35200e-c92b-4a93-8b88-b2c165409a20';\n", "import { defineObject, FieldType } from 'twenty-sdk/define';\n\nimport {\n  SESSION_CHANNEL_FIELD,\n  SESSION_CSAT_SCORE_FIELD,\n  SESSION_CTWA_CLID_FIELD,\n  SESSION_DURATION_SEC_FIELD,\n  SESSION_ENDED_AT_FIELD,\n  SESSION_EXTERNAL_ID_FIELD,\n  SESSION_META_AD_ID_FIELD,\n  SESSION_MOTIVE_FIELD,\n  SESSION_NAME_FIELD,\n  SESSION_STARTED_AT_FIELD,\n  SESSION_SUMMARY_FIELD,\n  SESSION_TALQUI_LEAD_ID_FIELD,\n  SESSION_UNIVERSAL_IDENTIFIER,\n  SESSION_URL_FIELD,\n  SESSION_UTM_CAMPAIGN_FIELD,\n  SESSION_UTM_CONTENT_FIELD,\n  SESSION_UTM_MEDIUM_FIELD,\n  SESSION_UTM_SOURCE_FIELD,\n} from 'src/constants/universal-identifiers';\n\n// Channel options are grouped by channel family. The Talqui core tracks\n// channels as URNs (talqui-core-api/commons/_consts.js); exposing the raw\n// URN in the CRM leaks provider detail and is unreadable, so the bridge\n// (plugin-crms) maps URN -> family before pushing data here.\n//\n// URN -> option contract:\n//   urn:talqui:whatsapp-cloud:0     -> WHATSAPP\n//   urn:talqui:whatsapp-dialog:0    -> WHATSAPP\n//   urn:talqui:whatsapp-gup:0       -> WHATSAPP\n//   urn:talqui:whatsapp-internal:0  -> WHATSAPP\n//   urn:talqui:whatsapp-zapi:0      -> WHATSAPP\n//   urn:talqui:instagram:0          -> INSTAGRAM\n//   urn:talqui:mercado-libre:0      -> MERCADOLIVRE\n//   urn:talqui:messenger:0          -> MESSENGER\n//   urn:talqui:telegram:0           -> TELEGRAM\n//   urn:talqui:chat-widget:0        -> WEBCHAT\n//   urn:talqui:ifood:0              -> IFOOD\n//   (reserved)                      -> EMAIL\n//   (unknown/future URNs)           -> OTHER\nexport enum SessionChannel {\n  WHATSAPP = 'WHATSAPP',\n  INSTAGRAM = 'INSTAGRAM',\n  MERCADOLIVRE = 'MERCADOLIVRE',\n  MESSENGER = 'MESSENGER',\n  TELEGRAM = 'TELEGRAM',\n  WEBCHAT = 'WEBCHAT',\n  IFOOD = 'IFOOD',\n  EMAIL = 'EMAIL',\n  OTHER = 'OTHER',\n}\n\n// Session-based data model; surfaced to the user as \"Conversation\".\nexport default defineObject({\n  universalIdentifier: SESSION_UNIVERSAL_IDENTIFIER,\n  nameSingular: 'session',\n  namePlural: 'sessions',\n  labelSingular: 'Conversation',\n  labelPlural: 'Conversations',\n  description: 'A Talqui customer-service session mirrored into the CRM. Points to the original session on the Talqui platform.',\n  icon: 'IconMessageCircle',\n  isSearchable: true,\n  labelIdentifierFieldMetadataUniversalIdentifier: SESSION_NAME_FIELD,\n  fields: [\n    {\n      universalIdentifier: SESSION_NAME_FIELD,\n      type: FieldType.TEXT,\n      name: 'name',\n      label: 'Title',\n      description: 'Session title. Filled by the events bridge (e.g. \"Conversation with {contact} \u2014 {date}\").',\n      icon: 'IconAbc',\n    },\n    {\n      universalIdentifier: SESSION_CHANNEL_FIELD,\n      type: FieldType.SELECT,\n      name: 'channel',\n      label: 'Channel',\n      description: 'Channel family the session happened on in Talqui.',\n      icon: 'IconPlug',\n      defaultValue: `'${SessionChannel.OTHER}'`,\n      options: [\n        {\n          id: 'fbded1c2-e797-4bbb-89b4-7fc4f3a3642e',\n          value: SessionChannel.WHATSAPP,\n          label: 'WhatsApp',\n          position: 0,\n          color: 'green',\n        },\n        {\n          id: '7be3b624-77ea-414f-bdad-24674c8370f5',\n          value: SessionChannel.INSTAGRAM,\n          label: 'Instagram',\n          position: 1,\n          color: 'pink',\n        },\n        {\n          id: '377ea49d-2420-47fd-befe-1653dc6f4e6f',\n          value: SessionChannel.MERCADOLIVRE,\n          label: 'Mercado Livre',\n          position: 2,\n          color: 'yellow',\n        },\n        {\n          id: 'd1dd2f89-76b2-4e50-92cf-7c29cfa8494a',\n          value: SessionChannel.MESSENGER,\n          label: 'Messenger',\n          position: 3,\n          color: 'blue',\n        },\n        {\n          id: '4ed6aa08-4d7a-4adb-ba62-8ce85453f602',\n          value: SessionChannel.TELEGRAM,\n          label: 'Telegram',\n          position: 4,\n          color: 'sky',\n        },\n        {\n          id: 'a6b72a68-bf11-4cb8-92ca-f77f2c230c86',\n          value: SessionChannel.WEBCHAT,\n          label: 'Webchat',\n          position: 5,\n          color: 'purple',\n        },\n        {\n          id: 'c2ca6adb-190d-4905-84cf-b40936031de3',\n          value: SessionChannel.IFOOD,\n          label: 'iFood',\n          position: 6,\n          color: 'red',\n        },\n        {\n          id: '9f7be3c9-9920-4bdb-8a46-fed5bad9cbc7',\n          value: SessionChannel.EMAIL,\n          label: 'Email',\n          position: 7,\n          color: 'gray',\n        },\n        {\n          id: 'f1e8aaf8-dca8-4ee3-8d7e-fbfa65d9c2f6',\n          value: SessionChannel.OTHER,\n          label: 'Other',\n          position: 8,\n          color: 'gray',\n        },\n      ],\n    },\n    {\n      universalIdentifier: SESSION_STARTED_AT_FIELD,\n      type: FieldType.DATE_TIME,\n      name: 'startedAt',\n      label: 'Started at',\n      description: 'When the session started on Talqui (session.createdAt).',\n      icon: 'IconCalendarTime',\n      isNullable: true,\n      defaultValue: null,\n    },\n    {\n      universalIdentifier: SESSION_ENDED_AT_FIELD,\n      type: FieldType.DATE_TIME,\n      name: 'endedAt',\n      label: 'Ended at',\n      description: 'When the session was closed on Talqui (session.closedAt).',\n      icon: 'IconCalendarOff',\n      isNullable: true,\n      defaultValue: null,\n    },\n    {\n      universalIdentifier: SESSION_DURATION_SEC_FIELD,\n      type: FieldType.NUMBER,\n      name: 'durationSec',\n      label: 'Duration (s)',\n      description: 'Session duration in seconds (endedAt - startedAt). Empty while the session is open.',\n      icon: 'IconClock',\n      isNullable: true,\n      defaultValue: null,\n    },\n    {\n      universalIdentifier: SESSION_URL_FIELD,\n      type: FieldType.LINKS,\n      name: 'url',\n      label: 'URL',\n      description: 'Deep link to the session in the Talqui inbox.',\n      icon: 'IconExternalLink',\n      isNullable: true,\n      defaultValue: null,\n    },\n    {\n      universalIdentifier: SESSION_EXTERNAL_ID_FIELD,\n      type: FieldType.TEXT,\n      name: 'externalId',\n      label: 'External ID',\n      description: 'Talqui sessionID. Upsert key for the events bridge \u2014 do not edit manually.',\n      icon: 'IconKey',\n    },\n    {\n      universalIdentifier: SESSION_SUMMARY_FIELD,\n      type: FieldType.TEXT,\n      name: 'summary',\n      label: 'Summary',\n      description: 'Session summary generated on Talqui (session.sessionSummary).',\n      icon: 'IconFileText',\n    },\n    {\n      universalIdentifier: SESSION_CSAT_SCORE_FIELD,\n      type: FieldType.RATING,\n      name: 'csatScore',\n      label: 'CSAT score',\n      description: 'Customer rating in stars (1-5). Empty when the contact did not rate \u2014 on Talqui, stars=0 means \"not rated\" and must never become 0 stars here.',\n      icon: 'IconStars',\n      isNullable: true,\n      defaultValue: null,\n      // RATING is enum-backed on the metadata engine: the sync rejects the\n      // field without explicit options. RATING_1..RATING_5 mirrors the\n      // values Twenty core generates for its own rating fields.\n      options: [\n        {\n          id: '21f992c8-421a-4908-b025-d8d1fe464128',\n          value: 'RATING_1',\n          label: '1',\n          position: 0,\n        },\n        {\n          id: 'cfa68be9-cd9e-44b2-9b91-b41535d0f7e0',\n          value: 'RATING_2',\n          label: '2',\n          position: 1,\n        },\n        {\n          id: '54eb2a42-8707-4f61-a0d7-7461568d0b72',\n          value: 'RATING_3',\n          label: '3',\n          position: 2,\n        },\n        {\n          id: '82ac27b9-2c28-4492-bcb7-aca4f6f34cef',\n          value: 'RATING_4',\n          label: '4',\n          position: 3,\n        },\n        {\n          id: 'b25c26f2-2c80-4986-8a97-86107b1e9276',\n          value: 'RATING_5',\n          label: '5',\n          position: 4,\n        },\n      ],\n    },\n    {\n      universalIdentifier: SESSION_MOTIVE_FIELD,\n      type: FieldType.TEXT,\n      name: 'serviceMotive',\n      label: 'Service motive',\n      description: 'Service/close motive recorded on Talqui (session.closeMotive).',\n      icon: 'IconFlag',\n    },\n    // Attribution \u2014 populated by the events bridge from the CTWA referral the\n    // Talqui core flattens onto session.sessionMeta. All nullable: only paid\n    // Click-to-WhatsApp conversations carry them.\n    {\n      universalIdentifier: SESSION_UTM_SOURCE_FIELD,\n      type: FieldType.TEXT,\n      name: 'utmSource',\n      label: 'UTM Source',\n      description: 'Traffic source of the conversation (CTWA: \"instagram\"). Set by the events bridge.',\n      icon: 'IconRoute',\n      isNullable: true,\n    },\n    {\n      universalIdentifier: SESSION_UTM_MEDIUM_FIELD,\n      type: FieldType.TEXT,\n      name: 'utmMedium',\n      label: 'UTM Medium',\n      description: 'Traffic medium of the conversation (CTWA: \"paid_social\"). Set by the events bridge.',\n      icon: 'IconRoute',\n      isNullable: true,\n    },\n    {\n      universalIdentifier: SESSION_UTM_CONTENT_FIELD,\n      type: FieldType.TEXT,\n      name: 'utmContent',\n      label: 'UTM Content',\n      description: 'Creative/ad identifier of the conversation (CTWA: the Meta ad id). Set by the events bridge.',\n      icon: 'IconRoute',\n      isNullable: true,\n    },\n    {\n      universalIdentifier: SESSION_UTM_CAMPAIGN_FIELD,\n      type: FieldType.TEXT,\n      name: 'utmCampaign',\n      label: 'UTM Campaign',\n      description: 'Campaign of the conversation. For CTWA the ad->campaign lookup is deferred to the CAPI phase; empty for now.',\n      icon: 'IconRoute',\n      isNullable: true,\n    },\n    {\n      universalIdentifier: SESSION_META_AD_ID_FIELD,\n      type: FieldType.TEXT,\n      name: 'metaAdId',\n      label: 'Meta Ad ID',\n      description: 'Meta ad the CTWA conversation came from (session.sessionMeta.referralSourceId). Set by the events bridge.',\n      icon: 'IconBrandMeta',\n      isNullable: true,\n    },\n    {\n      universalIdentifier: SESSION_CTWA_CLID_FIELD,\n      type: FieldType.TEXT,\n      name: 'ctwaClid',\n      label: 'CTWA Click ID',\n      description: 'Meta Click-to-WhatsApp click id (session.sessionMeta.referralCtwaClid) \u2014 key for Meta CAPI. Set by the events bridge.',\n      icon: 'IconBrandWhatsapp',\n      isNullable: true,\n    },\n    {\n      universalIdentifier: SESSION_TALQUI_LEAD_ID_FIELD,\n      type: FieldType.TEXT,\n      name: 'talquiLeadId',\n      label: 'Talqui Lead ID',\n      description: 'Talqui lead id (session.sessionMeta.tlID) \u2014 mirrors the opportunity key when the conversation carries one. Set by the events bridge.',\n      icon: 'IconTypography',\n      isNullable: true,\n    },\n  ],\n});\n"],
  "mappings": "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",
  "names": ["SessionChannel"]
}
