@chativa/connector-directline 0.7.2 → 0.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { DirectLine as v, ConnectionStatus as l } from "botframework-directlinejs";
2
- const f = /* @__PURE__ */ Symbol("typing"), k = "application/vnd.microsoft.card.hero", b = "application/vnd.microsoft.card.thumbnail", m = "application/vnd.microsoft.card.adaptive", S = "application/vnd.microsoft.card.signin", H = "application/vnd.microsoft.card.oauth", A = "application/vnd.microsoft.card.receipt", D = "application/vnd.microsoft.card.audio", E = "application/vnd.microsoft.card.video", $ = "application/vnd.microsoft.card.animation", T = "application/vnd.microsoft.card.flex";
2
+ const f = /* @__PURE__ */ Symbol("typing"), k = "application/vnd.microsoft.card.hero", b = "application/vnd.microsoft.card.thumbnail", m = "application/vnd.microsoft.card.adaptive", H = "application/vnd.microsoft.card.signin", A = "application/vnd.microsoft.card.oauth", D = "application/vnd.microsoft.card.receipt", E = "application/vnd.microsoft.card.audio", $ = "application/vnd.microsoft.card.video", N = "application/vnd.microsoft.card.animation", T = "application/vnd.microsoft.card.flex";
3
3
  function y(i, t) {
4
4
  if (i.from.id === t) return null;
5
5
  if (i.type === "typing") return f;
6
6
  if (i.type !== "message") return null;
7
- const e = i, n = e.id ?? `dl-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`, s = e.timestamp ? new Date(e.timestamp).getTime() : Date.now(), r = e.channelData, o = U(e);
7
+ const e = i, n = e.id ?? `dl-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`, s = e.timestamp ? new Date(e.timestamp).getTime() : Date.now(), r = e.channelData, o = R(e);
8
8
  if (e.attachments && e.attachments.length > 0) {
9
- const a = N(e, n, s);
9
+ const a = L(e, n, s);
10
10
  return a && (o.length > 0 && (a.actions = o), r && (a.data.channelData = r)), a;
11
11
  }
12
12
  return o.length > 0 ? {
@@ -23,21 +23,21 @@ function y(i, t) {
23
23
  timestamp: s
24
24
  } : null;
25
25
  }
26
- function N(i, t, e) {
26
+ function L(i, t, e) {
27
27
  const n = i.attachments, s = i.attachmentLayout, r = [k, b, T, m];
28
28
  return n.every((a) => r.includes(a.contentType)) && (n.length > 1 || s === "carousel") ? {
29
29
  id: t,
30
30
  type: "carousel",
31
31
  from: "bot",
32
32
  data: {
33
- cards: n.map((a) => a.contentType === m ? R(
33
+ cards: n.map((a) => a.contentType === m ? _(
34
34
  a.content
35
35
  ) : I(a.content))
36
36
  },
37
37
  timestamp: e
38
- } : L(n[0], i, t, e);
38
+ } : U(n[0], i, t, e);
39
39
  }
40
- function L(i, t, e, n) {
40
+ function U(i, t, e, n) {
41
41
  const s = i.contentType;
42
42
  if (s === k || s === b || s === T) {
43
43
  const r = i.content;
@@ -50,8 +50,8 @@ function L(i, t, e, n) {
50
50
  };
51
51
  }
52
52
  if (s === m)
53
- return _(i.content, e, n);
54
- if (s === S || s === H) {
53
+ return O(i.content, e, n);
54
+ if (s === H || s === A) {
55
55
  const r = i.content;
56
56
  return {
57
57
  id: e,
@@ -59,14 +59,14 @@ function L(i, t, e, n) {
59
59
  from: "bot",
60
60
  data: {
61
61
  text: r.text ?? "Please sign in",
62
- buttons: w(r.buttons)
62
+ buttons: C(r.buttons)
63
63
  },
64
64
  timestamp: n
65
65
  };
66
66
  }
67
- if (s === A)
68
- return O(i.content, e, n);
69
- if (s === E) {
67
+ if (s === D)
68
+ return P(i.content, e, n);
69
+ if (s === $) {
70
70
  const r = i.content, o = r.media?.[0]?.url;
71
71
  return o ? {
72
72
  id: e,
@@ -80,7 +80,7 @@ function L(i, t, e, n) {
80
80
  timestamp: n
81
81
  } : null;
82
82
  }
83
- if (s === D) {
83
+ if (s === E) {
84
84
  const r = i.content, o = r.media?.[0]?.url;
85
85
  return o ? {
86
86
  id: e,
@@ -94,7 +94,7 @@ function L(i, t, e, n) {
94
94
  timestamp: n
95
95
  } : null;
96
96
  }
97
- if (s === $) {
97
+ if (s === N) {
98
98
  const r = i.content, o = r.media?.[0]?.url;
99
99
  return o ? {
100
100
  id: e,
@@ -143,10 +143,10 @@ function I(i) {
143
143
  image: i.images?.[0]?.url,
144
144
  title: i.title ?? "",
145
145
  subtitle: i.subtitle ?? i.text,
146
- buttons: w(i.buttons)
146
+ buttons: C(i.buttons)
147
147
  };
148
148
  }
149
- function w(i) {
149
+ function C(i) {
150
150
  return !i || i.length === 0 ? [] : i.map((t) => {
151
151
  const e = ("title" in t ? t.title : void 0) ?? String(t.value ?? "");
152
152
  switch (t.type) {
@@ -160,7 +160,7 @@ function w(i) {
160
160
  }
161
161
  });
162
162
  }
163
- function U(i) {
163
+ function R(i) {
164
164
  const t = i.suggestedActions?.actions;
165
165
  return !t || t.length === 0 ? [] : t.map((e) => {
166
166
  const n = ("title" in e ? e.title : void 0) ?? String(e.value ?? "");
@@ -192,7 +192,7 @@ function d(i, t, e, n) {
192
192
  break;
193
193
  }
194
194
  }
195
- function C(i) {
195
+ function w(i) {
196
196
  const t = [];
197
197
  let e;
198
198
  const n = [];
@@ -205,8 +205,8 @@ function C(i) {
205
205
  }
206
206
  ), Array.isArray(i.actions) && x(i.actions, n), { texts: t, image: e, buttons: n };
207
207
  }
208
- function R(i) {
209
- const { texts: t, image: e, buttons: n } = C(i);
208
+ function _(i) {
209
+ const { texts: t, image: e, buttons: n } = w(i);
210
210
  return {
211
211
  image: e,
212
212
  title: t[0] ?? "",
@@ -215,8 +215,8 @@ function R(i) {
215
215
  buttons: n
216
216
  };
217
217
  }
218
- function _(i, t, e) {
219
- const { texts: n, image: s, buttons: r } = C(i), o = i.fallbackText ?? i.speak ?? n.join(`
218
+ function O(i, t, e) {
219
+ const { texts: n, image: s, buttons: r } = w(i), o = i.fallbackText ?? i.speak ?? n.join(`
220
220
  `);
221
221
  return s ? {
222
222
  id: t,
@@ -253,7 +253,7 @@ function x(i, t) {
253
253
  e.type === "Action.OpenUrl" && e.url ? t.push({ label: n, url: e.url }) : e.type === "Action.Submit" ? t.push({ label: n, value: typeof e.data == "string" ? e.data : n }) : t.push({ label: n, value: n });
254
254
  }
255
255
  }
256
- function O(i, t, e) {
256
+ function P(i, t, e) {
257
257
  const n = [];
258
258
  if (i.title && n.push(`**${i.title}**`), i.facts)
259
259
  for (const s of i.facts)
@@ -273,20 +273,23 @@ function O(i, t, e) {
273
273
  };
274
274
  }
275
275
  const g = "chativa_directline_userId", h = "chativa_directline_conversation";
276
- function P() {
276
+ function S() {
277
+ return Math.random().toString(36).slice(2, 15) + Math.random().toString(36).slice(2, 15);
278
+ }
279
+ function B() {
277
280
  try {
278
281
  const t = localStorage.getItem(g);
279
282
  if (t) return t;
280
283
  } catch {
281
284
  }
282
- const i = Math.random().toString(36).slice(2, 15) + Math.random().toString(36).slice(2, 15);
285
+ const i = S();
283
286
  try {
284
287
  localStorage.setItem(g, i);
285
288
  } catch {
286
289
  }
287
290
  return i;
288
291
  }
289
- function B(i) {
292
+ function F(i) {
290
293
  try {
291
294
  const t = JSON.parse(atob(i.split(".")[1]));
292
295
  return typeof t.exp == "number" ? t.exp * 1e3 : null;
@@ -294,7 +297,7 @@ function B(i) {
294
297
  return null;
295
298
  }
296
299
  }
297
- async function F(i, t) {
300
+ async function j(i, t) {
298
301
  const e = await fetch(
299
302
  "https://directline.botframework.com/v3/directline/tokens/generate",
300
303
  {
@@ -311,7 +314,7 @@ async function F(i, t) {
311
314
  const n = await e.json();
312
315
  return { token: n.token, conversationId: n.conversationId };
313
316
  }
314
- async function j(i) {
317
+ async function M(i) {
315
318
  const t = await fetch(i, { method: "POST" });
316
319
  if (!t.ok)
317
320
  throw new Error(`Token generator failed: ${t.status}`);
@@ -326,7 +329,7 @@ async function u(i, t) {
326
329
  throw new Error(`Token refresh failed: ${n.status}`);
327
330
  return await n.json();
328
331
  }
329
- class J {
332
+ class G {
330
333
  constructor(t) {
331
334
  this.name = "directline", this.addSentToHistory = !0, this.chativaCtx = null, this.messageHandler = null, this.connectHandler = null, this.disconnectHandler = null, this.typingHandler = null, this.messageStatusHandler = null, this.activitySub = null, this.connectionSub = null, this.typingTimeout = null, this.refreshTimer = null, this.pendingIds = [], this.hasConnectedBefore = !1, this.resolveReady = null, this._skipNextJoin = !1, this.options = t;
332
335
  }
@@ -362,7 +365,7 @@ class J {
362
365
  return Object.keys(this.options.eventHandlers ?? {});
363
366
  }
364
367
  async connect() {
365
- this.userId = this.options.userId ?? P(), this.userName = this.options.userName;
368
+ this.userId = this.options.userId ?? (this.options.resumeConversation ? B() : S()), this.userName = this.options.userName;
366
369
  let t = !1;
367
370
  if (this.options.resumeConversation) {
368
371
  const n = this.loadPersistedConversation();
@@ -379,14 +382,14 @@ class J {
379
382
  }
380
383
  if (!t)
381
384
  if (this.options.tokenGeneratorUrl) {
382
- const n = await j(
385
+ const n = await M(
383
386
  this.options.tokenGeneratorUrl
384
387
  );
385
388
  this.token = n.token, n.conversationId && (this.conversationId = n.conversationId), n.userId && (this.userId = n.userId);
386
389
  } else if (this.options.token)
387
390
  this.token = this.options.token;
388
391
  else if (this.options.secret) {
389
- const n = await F(
392
+ const n = await j(
390
393
  this.options.secret,
391
394
  this.userId
392
395
  );
@@ -669,7 +672,7 @@ class J {
669
672
  /** Schedule a token refresh 60 seconds before expiry. */
670
673
  scheduleTokenRefresh() {
671
674
  this.clearRefreshTimer();
672
- const t = B(this.token);
675
+ const t = F(this.token);
673
676
  if (!t) return;
674
677
  const e = t - Date.now() - 6e4;
675
678
  if (e <= 0) {
@@ -750,6 +753,6 @@ class J {
750
753
  }
751
754
  }
752
755
  export {
753
- J as DirectLineConnector
756
+ G as DirectLineConnector
754
757
  };
755
758
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/mapActivity.ts","../src/DirectLineConnector.ts"],"sourcesContent":["/**\n * Pure mapping functions that convert DirectLine activities\n * into Chativa IncomingMessage structures.\n *\n * No side-effects — all functions are stateless and easily testable.\n */\n\nimport type {\n Activity,\n Message,\n CardAction,\n Attachment,\n HeroCard,\n Thumbnail,\n Signin,\n Receipt,\n AudioCard,\n VideoCard,\n AnimationCard,\n AdaptiveCard,\n FlexCard,\n} from \"botframework-directlinejs\";\nimport type { IncomingMessage, MessageAction } from \"@chativa/core\";\n\n/* ------------------------------------------------------------------ */\n/* Sentinel returned for typing activities */\n/* ------------------------------------------------------------------ */\n\nexport const TYPING_SENTINEL = Symbol(\"typing\");\nexport type MapResult = IncomingMessage | typeof TYPING_SENTINEL | null;\n\n/* ------------------------------------------------------------------ */\n/* Content-type constants */\n/* ------------------------------------------------------------------ */\n\nconst CT_HERO = \"application/vnd.microsoft.card.hero\";\nconst CT_THUMBNAIL = \"application/vnd.microsoft.card.thumbnail\";\nconst CT_ADAPTIVE = \"application/vnd.microsoft.card.adaptive\";\nconst CT_SIGNIN = \"application/vnd.microsoft.card.signin\";\nconst CT_OAUTH = \"application/vnd.microsoft.card.oauth\";\nconst CT_RECEIPT = \"application/vnd.microsoft.card.receipt\";\nconst CT_AUDIO = \"application/vnd.microsoft.card.audio\";\nconst CT_VIDEO = \"application/vnd.microsoft.card.video\";\nconst CT_ANIMATION = \"application/vnd.microsoft.card.animation\";\nconst CT_FLEX = \"application/vnd.microsoft.card.flex\";\n\n/* ------------------------------------------------------------------ */\n/* Main entry point */\n/* ------------------------------------------------------------------ */\n\n/**\n * Convert a DirectLine Activity into a Chativa IncomingMessage.\n *\n * Returns:\n * - `IncomingMessage` for renderable messages\n * - `TYPING_SENTINEL` for typing indicators (handled by the connector)\n * - `null` for activities that should be ignored (echo, events, etc.)\n */\nexport function mapActivityToMessage(\n activity: Activity,\n userId: string,\n): MapResult {\n // Filter out echoed user messages\n if (activity.from.id === userId) return null;\n\n // Typing indicator\n if (activity.type === \"typing\") return TYPING_SENTINEL;\n\n // Only process message activities\n if (activity.type !== \"message\") return null;\n\n const msg = activity as Message;\n const id = msg.id ?? `dl-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n const timestamp = msg.timestamp ? new Date(msg.timestamp).getTime() : Date.now();\n\n // Preserve channelData (e.g. correlationId used for feedback)\n const channelData = (msg as unknown as { channelData?: Record<string, unknown> }).channelData;\n\n // Map suggested actions (may be used as top-level actions or as quick-reply)\n const suggestedActions = mapSuggestedActions(msg);\n\n // If there are attachments, process them\n if (msg.attachments && msg.attachments.length > 0) {\n const result = mapAttachments(msg, id, timestamp);\n if (result) {\n if (suggestedActions.length > 0) result.actions = suggestedActions;\n if (channelData) result.data.channelData = channelData;\n }\n return result;\n }\n\n // Text + suggested actions → quick-reply\n if (suggestedActions.length > 0) {\n return {\n id,\n type: \"quick-reply\",\n from: \"bot\",\n data: { text: msg.text ?? \"\", actions: suggestedActions, ...(channelData ? { channelData } : {}) },\n timestamp,\n };\n }\n\n // Plain text\n if (msg.text) {\n return {\n id,\n type: \"text\",\n from: \"bot\",\n data: { text: msg.text, ...(channelData ? { channelData } : {}) },\n timestamp,\n };\n }\n\n // Nothing meaningful\n return null;\n}\n\n/* ------------------------------------------------------------------ */\n/* Attachment mapping */\n/* ------------------------------------------------------------------ */\n\nfunction mapAttachments(\n msg: Message,\n id: string,\n timestamp: number,\n): IncomingMessage | null {\n const attachments = msg.attachments!;\n const layout = msg.attachmentLayout;\n\n // Multiple cards with carousel layout\n const cardTypes = [CT_HERO, CT_THUMBNAIL, CT_FLEX, CT_ADAPTIVE];\n const allCards = attachments.every((a) => cardTypes.includes(a.contentType));\n\n if (allCards && (attachments.length > 1 || layout === \"carousel\")) {\n return {\n id,\n type: \"carousel\",\n from: \"bot\",\n data: {\n cards: attachments.map((a) => {\n if (a.contentType === CT_ADAPTIVE) {\n return adaptiveCardToCardData(\n (a as AdaptiveCard).content as Record<string, unknown>,\n );\n }\n return mapHeroLikeCard((a as HeroCard | Thumbnail | FlexCard).content);\n }),\n },\n timestamp,\n };\n }\n\n // Single attachment\n return mapSingleAttachment(attachments[0], msg, id, timestamp);\n}\n\nfunction mapSingleAttachment(\n att: Attachment,\n msg: Message,\n id: string,\n timestamp: number,\n): IncomingMessage | null {\n const ct = att.contentType;\n\n // Hero / Thumbnail / Flex card\n if (ct === CT_HERO || ct === CT_THUMBNAIL || ct === CT_FLEX) {\n const content = (att as HeroCard | Thumbnail | FlexCard).content;\n return {\n id,\n type: \"card\",\n from: \"bot\",\n data: mapHeroLikeCard(content),\n timestamp,\n };\n }\n\n // Adaptive card — simple parse\n if (ct === CT_ADAPTIVE) {\n return mapAdaptiveCard((att as AdaptiveCard).content, id, timestamp);\n }\n\n // Signin / OAuth card\n if (ct === CT_SIGNIN || ct === CT_OAUTH) {\n const content = (att as Signin).content;\n return {\n id,\n type: \"buttons\",\n from: \"bot\",\n data: {\n text: content.text ?? \"Please sign in\",\n buttons: mapCardButtons(content.buttons),\n },\n timestamp,\n };\n }\n\n // Receipt card\n if (ct === CT_RECEIPT) {\n return mapReceiptCard((att as Receipt).content, id, timestamp);\n }\n\n // Video card\n if (ct === CT_VIDEO) {\n const content = (att as VideoCard).content;\n const mediaUrl = content.media?.[0]?.url;\n if (!mediaUrl) return null;\n return {\n id,\n type: \"video\",\n from: \"bot\",\n data: {\n src: mediaUrl,\n poster: content.image?.url,\n caption: content.title ?? msg.text,\n },\n timestamp,\n };\n }\n\n // Audio card\n if (ct === CT_AUDIO) {\n const content = (att as AudioCard).content;\n const mediaUrl = content.media?.[0]?.url;\n if (!mediaUrl) return null;\n return {\n id,\n type: \"file\",\n from: \"bot\",\n data: {\n url: mediaUrl,\n name: content.title ?? \"audio\",\n mimeType: \"audio/mpeg\",\n },\n timestamp,\n };\n }\n\n // Animation card (typically GIFs)\n if (ct === CT_ANIMATION) {\n const content = (att as AnimationCard).content;\n const mediaUrl = content.media?.[0]?.url;\n if (!mediaUrl) return null;\n return {\n id,\n type: \"image\",\n from: \"bot\",\n data: {\n src: mediaUrl,\n caption: content.title ?? msg.text,\n },\n timestamp,\n };\n }\n\n // Image attachment (contentType starts with \"image/\")\n if (ct.startsWith(\"image/\") && \"contentUrl\" in att) {\n return {\n id,\n type: \"image\",\n from: \"bot\",\n data: {\n src: att.contentUrl,\n alt: att.name,\n caption: msg.text,\n },\n timestamp,\n };\n }\n\n // Video file attachment\n if (ct.startsWith(\"video/\") && \"contentUrl\" in att) {\n return {\n id,\n type: \"video\",\n from: \"bot\",\n data: {\n src: att.contentUrl,\n caption: msg.text,\n },\n timestamp,\n };\n }\n\n // Generic file attachment\n if (\"contentUrl\" in att) {\n return {\n id,\n type: \"file\",\n from: \"bot\",\n data: {\n url: att.contentUrl,\n name: att.name ?? \"file\",\n mimeType: ct,\n },\n timestamp,\n };\n }\n\n return null;\n}\n\n/* ------------------------------------------------------------------ */\n/* Hero-like card mapping (hero, thumbnail, flex share same shape) */\n/* ------------------------------------------------------------------ */\n\nfunction mapHeroLikeCard(content: HeroCard[\"content\"]): Record<string, unknown> {\n return {\n image: content.images?.[0]?.url,\n title: content.title ?? \"\",\n subtitle: content.subtitle ?? content.text,\n buttons: mapCardButtons(content.buttons),\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Card button / action mapping */\n/* ------------------------------------------------------------------ */\n\nexport function mapCardButtons(\n buttons?: CardAction[],\n): MessageAction[] {\n if (!buttons || buttons.length === 0) return [];\n\n return buttons.map((btn): MessageAction => {\n const label = (\"title\" in btn ? btn.title : undefined) ?? String(btn.value ?? \"\");\n\n switch (btn.type) {\n case \"openUrl\":\n case \"signin\":\n return { label, url: String(btn.value ?? \"\") };\n\n case \"call\":\n return { label, url: String(btn.value ?? \"\") };\n\n case \"imBack\":\n case \"postBack\":\n case \"messageBack\":\n default:\n return { label, value: String(btn.value ?? label) };\n }\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Suggested actions mapping */\n/* ------------------------------------------------------------------ */\n\nfunction mapSuggestedActions(msg: Message): MessageAction[] {\n const actions = msg.suggestedActions?.actions;\n if (!actions || actions.length === 0) return [];\n\n return actions.map((a): MessageAction => {\n const label = (\"title\" in a ? a.title : undefined) ?? String(a.value ?? \"\");\n if (a.type === \"openUrl\") {\n return { label, url: String(a.value ?? \"\") };\n }\n return { label, value: String(a.value ?? label) };\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Adaptive Card — simple parse */\n/* ------------------------------------------------------------------ */\n\ninterface AdaptiveElement {\n type: string;\n text?: string;\n url?: string;\n body?: AdaptiveElement[];\n items?: AdaptiveElement[];\n columns?: Array<{ items?: AdaptiveElement[] }>;\n actions?: Array<{ type: string; title?: string; url?: string; data?: unknown }>;\n [key: string]: unknown;\n}\n\n/** Recursively walk Adaptive Card elements and collect texts, the first image, and buttons. */\nfunction walkAdaptiveElements(\n elements: AdaptiveElement[] | undefined,\n texts: string[],\n buttons: MessageAction[],\n onImage: (url: string) => void,\n) {\n if (!elements) return;\n for (const el of elements) {\n switch (el.type) {\n case \"TextBlock\":\n if (el.text) texts.push(el.text);\n break;\n case \"Image\":\n if (el.url) onImage(el.url);\n break;\n case \"ActionSet\":\n if (el.actions) mapAdaptiveActions(el.actions, buttons);\n break;\n case \"Container\":\n walkAdaptiveElements(el.items, texts, buttons, onImage);\n break;\n case \"ColumnSet\":\n for (const col of el.columns ?? []) {\n walkAdaptiveElements(col.items, texts, buttons, onImage);\n }\n break;\n case \"Column\":\n walkAdaptiveElements(el.items, texts, buttons, onImage);\n break;\n }\n }\n}\n\n/** Parse an Adaptive Card body into { image, title, subtitle, buttons }. */\nfunction parseAdaptiveCardBody(content: Record<string, unknown>) {\n const texts: string[] = [];\n let image: string | undefined;\n const buttons: MessageAction[] = [];\n\n walkAdaptiveElements(\n content.body as AdaptiveElement[] | undefined,\n texts,\n buttons,\n (url) => { image = image ?? url; },\n );\n\n if (Array.isArray(content.actions)) {\n mapAdaptiveActions(content.actions as AdaptiveElement[\"actions\"] & object, buttons);\n }\n\n return { texts, image, buttons };\n}\n\n/**\n * Extract card-like data from an Adaptive Card — used inside carousels.\n */\nfunction adaptiveCardToCardData(\n content: Record<string, unknown>,\n): Record<string, unknown> {\n const { texts, image, buttons } = parseAdaptiveCardBody(content);\n return {\n image,\n title: texts[0] ?? \"\",\n subtitle: texts.slice(1).join(\"\\n\"),\n buttons,\n };\n}\n\nfunction mapAdaptiveCard(\n content: Record<string, unknown>,\n id: string,\n timestamp: number,\n): IncomingMessage {\n const { texts, image, buttons } = parseAdaptiveCardBody(content);\n\n // Fallback text\n const fallback =\n (content.fallbackText as string) ??\n (content.speak as string) ??\n texts.join(\"\\n\");\n\n // If we have an image and a title, render as card\n if (image) {\n return {\n id,\n type: \"card\",\n from: \"bot\",\n data: {\n image,\n title: texts[0] ?? \"\",\n subtitle: texts.slice(1).join(\"\\n\"),\n buttons,\n },\n timestamp,\n };\n }\n\n // If we have buttons, render as buttons message\n if (buttons.length > 0) {\n return {\n id,\n type: \"buttons\",\n from: \"bot\",\n data: {\n text: fallback || \"Adaptive Card\",\n buttons,\n },\n timestamp,\n };\n }\n\n // Plain text fallback\n return {\n id,\n type: \"text\",\n from: \"bot\",\n data: { text: fallback || \"[Adaptive Card]\" },\n timestamp,\n };\n}\n\nfunction mapAdaptiveActions(\n actions: Array<{ type: string; title?: string; url?: string; data?: unknown }>,\n out: MessageAction[],\n) {\n for (const a of actions) {\n const label = a.title ?? \"Action\";\n if (a.type === \"Action.OpenUrl\" && a.url) {\n out.push({ label, url: a.url });\n } else if (a.type === \"Action.Submit\") {\n out.push({ label, value: typeof a.data === \"string\" ? a.data : label });\n } else {\n out.push({ label, value: label });\n }\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Receipt card mapping */\n/* ------------------------------------------------------------------ */\n\nfunction mapReceiptCard(\n content: Receipt[\"content\"],\n id: string,\n timestamp: number,\n): IncomingMessage {\n const lines: string[] = [];\n if (content.title) lines.push(`**${content.title}**`);\n\n if (content.facts) {\n for (const fact of content.facts) {\n lines.push(`${fact.key}: ${fact.value}`);\n }\n }\n\n if (content.items) {\n for (const item of content.items) {\n const price = item.price ? ` — ${item.price}` : \"\";\n lines.push(`- ${item.title ?? \"Item\"}${price}`);\n }\n }\n\n if (content.tax) lines.push(`Tax: ${content.tax}`);\n if (content.total) lines.push(`**Total: ${content.total}**`);\n\n return {\n id,\n type: \"text\",\n from: \"bot\",\n data: { text: lines.join(\"\\n\") },\n timestamp,\n };\n}\n","import type {\n IConnector,\n MessageHandler,\n ConnectHandler,\n DisconnectHandler,\n TypingHandler,\n MessageStatusHandler,\n ChativaContext,\n SurveyPayload,\n} from \"@chativa/core\";\nimport type {\n OutgoingMessage,\n HistoryResult,\n IncomingMessage,\n} from \"@chativa/core\";\nimport { DirectLine, ConnectionStatus } from \"botframework-directlinejs\";\nimport type { Activity } from \"botframework-directlinejs\";\nimport { mapActivityToMessage, TYPING_SENTINEL } from \"./mapActivity\";\n\n/** Minimal subscription interface returned by RxJS5 Observable.subscribe(). */\ninterface Unsubscribable {\n unsubscribe(): void;\n}\n\n/**\n * Context passed to custom event handlers — provides the info and methods\n * needed to respond to a bot-initiated event activity.\n */\nexport interface EventHandlerContext {\n /** The raw DirectLine event activity. */\n activity: Activity;\n /** The user ID for this session. */\n userId: string;\n /** The user display name for this session. */\n userName: string;\n /** Send an event activity back to the bot. */\n postEvent(name: string, value?: unknown): void;\n /**\n * Full Chativa context — access messages, chat UI, theme, and event bus.\n * Available when the connector is used via ChatEngine (which injects it).\n */\n chativa: ChativaContext;\n}\n\n/**\n * Handler for a bot-initiated event activity.\n * Keyed by event name (e.g. `\"LocationRequest\"`).\n */\nexport type EventHandler = (ctx: EventHandlerContext) => void;\n\nexport interface DirectLineConnectorOptions {\n /** DirectLine channel secret (server-side only — generates a token). */\n secret?: string;\n /** Pre-fetched DirectLine token. */\n token?: string;\n /** URL of a custom token-generating endpoint (POST, returns { token, conversationId? }). */\n tokenGeneratorUrl?: string;\n /** Override the user ID instead of auto-generating one. */\n userId?: string;\n /** Display name sent with activities. */\n userName?: string;\n /** Sovereign-cloud DirectLine endpoint (e.g. government, china). */\n domain?: string;\n /** BCP-47 locale sent with the webchat/join event and outgoing activities (e.g. \"tr-TR\"). */\n locale?: string;\n /**\n * Extra key-value pairs merged into the `webchat/join` event's `value` payload.\n * Example: `{ language: \"tr\", tenant: \"galataport\" }`\n */\n joinParameters?: Record<string, unknown>;\n /**\n * Custom handlers for bot-initiated event activities, keyed by event name.\n * Example:\n * ```ts\n * eventHandlers: {\n * LocationRequest: (ctx) => {\n * navigator.geolocation.getCurrentPosition((pos) => {\n * ctx.postEvent(\"webchat/location\", {\n * latitude: pos.coords.latitude,\n * longitude: pos.coords.longitude,\n * });\n * });\n * },\n * }\n * ```\n */\n eventHandlers?: Record<string, EventHandler>;\n /**\n * When true, persist conversation state (conversationId, token, watermark)\n * to localStorage so the conversation can be resumed across page reloads.\n */\n resumeConversation?: boolean;\n /**\n * How long (ms) to keep the typing indicator visible after a bot typing\n * signal before auto-clearing it. Each new typing signal resets the timer.\n * Default: 3000. Ignored when `typingUntilMessage` is true.\n */\n typingTimeoutMs?: number;\n /**\n * When true, the typing indicator stays on until the next bot message\n * arrives (no auto-clear timeout).\n */\n typingUntilMessage?: boolean;\n}\n\n/* ── Constants ────────────────────────────────────────────────────── */\n\nconst USER_ID_KEY = \"chativa_directline_userId\";\nconst CONVERSATION_KEY = \"chativa_directline_conversation\";\n\ninterface PersistedConversation {\n conversationId: string;\n token: string;\n watermark?: string;\n userId: string;\n}\n\n/* ── Module-level helpers ─────────────────────────────────────────── */\n\nfunction getOrCreateUserId(): string {\n try {\n const stored = localStorage.getItem(USER_ID_KEY);\n if (stored) return stored;\n } catch {\n // localStorage unavailable (e.g. incognito, SSR)\n }\n const id =\n Math.random().toString(36).slice(2, 15) +\n Math.random().toString(36).slice(2, 15);\n try {\n localStorage.setItem(USER_ID_KEY, id);\n } catch {\n // best-effort\n }\n return id;\n}\n\n/** Extract expiry time (ms since epoch) from a JWT token. */\nfunction getTokenExpiry(token: string): number | null {\n try {\n const payload = JSON.parse(atob(token.split(\".\")[1]));\n return typeof payload.exp === \"number\" ? payload.exp * 1000 : null;\n } catch {\n return null;\n }\n}\n\nasync function fetchToken(\n secret: string,\n userId: string,\n): Promise<{ token: string; conversationId: string }> {\n const res = await fetch(\n \"https://directline.botframework.com/v3/directline/tokens/generate\",\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${secret}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ user: { id: userId, name: userId } }),\n },\n );\n if (!res.ok) {\n throw new Error(`DirectLine token fetch failed: ${res.status}`);\n }\n const data = (await res.json()) as {\n token: string;\n conversationId: string;\n };\n return { token: data.token, conversationId: data.conversationId };\n}\n\nasync function fetchTokenFromUrl(\n url: string,\n): Promise<{ token: string; conversationId?: string; userId?: string }> {\n const res = await fetch(url, { method: \"POST\" });\n if (!res.ok) {\n throw new Error(`Token generator failed: ${res.status}`);\n }\n return (await res.json()) as {\n token: string;\n conversationId?: string;\n userId?: string;\n };\n}\n\n/** Refresh an existing DirectLine token via the REST API. */\nasync function refreshDirectLineToken(\n currentToken: string,\n domain?: string,\n): Promise<{ token: string; conversationId: string }> {\n const base = domain ?? \"https://directline.botframework.com/v3/directline\";\n const res = await fetch(`${base}/tokens/refresh`, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${currentToken}` },\n });\n if (!res.ok) {\n throw new Error(`Token refresh failed: ${res.status}`);\n }\n return (await res.json()) as { token: string; conversationId: string };\n}\n\n/**\n * DirectLineConnector — Azure Bot Framework DirectLine v3 adapter.\n *\n * Maps all Bot Framework activity types (hero cards, carousels,\n * suggested actions, images, videos, files, adaptive cards, etc.)\n * into Chativa's native message types.\n */\nexport class DirectLineConnector implements IConnector {\n readonly name = \"directline\";\n readonly addSentToHistory = true;\n\n private directLine!: DirectLine;\n private conversationId!: string;\n private userId!: string;\n private userName: string | undefined;\n private token!: string;\n private options: DirectLineConnectorOptions;\n private chativaCtx: ChativaContext | null = null;\n\n private messageHandler: MessageHandler | null = null;\n private connectHandler: ConnectHandler | null = null;\n private disconnectHandler: DisconnectHandler | null = null;\n private typingHandler: TypingHandler | null = null;\n private messageStatusHandler: MessageStatusHandler | null = null;\n\n private activitySub: Unsubscribable | null = null;\n private connectionSub: Unsubscribable | null = null;\n private typingTimeout: ReturnType<typeof setTimeout> | null = null;\n private refreshTimer: ReturnType<typeof setTimeout> | null = null;\n /** Queue of sent message IDs awaiting echo confirmation. */\n private pendingIds: string[] = [];\n /** True after the first successful connection (reserved for future join-vs-rejoin logic). */\n private hasConnectedBefore = false;\n /** Resolves the connect() promise once the bot sends its first message after join. */\n private resolveReady: (() => void) | null = null;\n /** Last known activity watermark — used for conversation resume. */\n private watermark: string | undefined;\n /** When true, skip the next join/rejoin event (used during resume). */\n private _skipNextJoin = false;\n\n constructor(options: DirectLineConnectorOptions) {\n this.options = options;\n }\n\n setContext(ctx: ChativaContext): void {\n this.chativaCtx = ctx;\n }\n\n /**\n * Register (or replace) an event handler for a bot-initiated event activity.\n * Can be called before or after `connect()`.\n *\n * @example\n * ```ts\n * connector.addEventHandler(\"LocationRequest\", (ctx) => {\n * navigator.geolocation.getCurrentPosition((pos) => {\n * ctx.postEvent(\"webchat/location\", { latitude: pos.coords.latitude, ... });\n * });\n * });\n * ```\n */\n addEventHandler(name: string, handler: EventHandler): void {\n this.options.eventHandlers ??= {};\n this.options.eventHandlers[name] = handler;\n }\n\n /** Remove a previously registered event handler by name. */\n removeEventHandler(name: string): boolean {\n if (!this.options.eventHandlers?.[name]) return false;\n delete this.options.eventHandlers[name];\n return true;\n }\n\n /** Check whether an event handler is registered for the given name. */\n hasEventHandler(name: string): boolean {\n return !!this.options.eventHandlers?.[name];\n }\n\n /** Return the names of all registered event handlers. */\n getEventHandlerNames(): string[] {\n return Object.keys(this.options.eventHandlers ?? {});\n }\n\n async connect(): Promise<void> {\n this.userId = this.options.userId ?? getOrCreateUserId();\n this.userName = this.options.userName;\n\n // ── Try to resume a persisted conversation ────────────────────\n let isResuming = false;\n if (this.options.resumeConversation) {\n const persisted = this.loadPersistedConversation();\n if (persisted) {\n try {\n const refreshed = await refreshDirectLineToken(\n persisted.token,\n this.options.domain,\n );\n this.token = refreshed.token;\n this.conversationId = persisted.conversationId;\n this.watermark = persisted.watermark;\n this.userId = persisted.userId;\n isResuming = true;\n } catch {\n // Persisted token expired or invalid — start fresh\n this.clearPersistedConversation();\n }\n }\n }\n\n // ── Acquire token (fresh conversation) ────────────────────────\n if (!isResuming) {\n if (this.options.tokenGeneratorUrl) {\n const result = await fetchTokenFromUrl(\n this.options.tokenGeneratorUrl,\n );\n this.token = result.token;\n if (result.conversationId)\n this.conversationId = result.conversationId;\n if (result.userId) this.userId = result.userId;\n } else if (this.options.token) {\n this.token = this.options.token;\n } else if (this.options.secret) {\n const result = await fetchToken(\n this.options.secret,\n this.userId,\n );\n this.token = result.token;\n this.conversationId = result.conversationId;\n } else {\n throw new Error(\n \"DirectLineConnector: provide token, secret, or tokenGeneratorUrl.\",\n );\n }\n }\n\n // ── Schedule automatic token refresh ──────────────────────────\n this.scheduleTokenRefresh();\n\n // ── Create DirectLine instance ────────────────────────────────\n this.directLine = new DirectLine({\n token: this.token,\n domain: this.options.domain,\n ...(isResuming\n ? {\n conversationId: this.conversationId,\n watermark: this.watermark,\n }\n : {}),\n });\n\n if (isResuming) {\n this.hasConnectedBefore = true;\n this._skipNextJoin = true;\n }\n\n // ── Wait for connection ───────────────────────────────────────\n const ready = new Promise<void>((resolve) => {\n this.resolveReady = resolve;\n });\n\n this.startListening(isResuming);\n\n await ready;\n this.connectHandler?.();\n\n if (this.options.resumeConversation) {\n this.persistConversation();\n }\n }\n\n async disconnect(): Promise<void> {\n this.activitySub?.unsubscribe();\n this.activitySub = null;\n this.connectionSub?.unsubscribe();\n this.connectionSub = null;\n this.clearTypingTimeout();\n this.clearRefreshTimer();\n\n try {\n this.directLine?.end();\n } catch {\n // DirectLine.end() may throw if already ended\n }\n\n this.messageHandler = null;\n this.connectHandler = null;\n this.disconnectHandler = null;\n this.typingHandler = null;\n this.messageStatusHandler = null;\n }\n\n /** Clear persisted conversation state and reset watermark. */\n clearConversation(): void {\n this.watermark = undefined;\n this.clearPersistedConversation();\n }\n\n async sendMessage(message: OutgoingMessage): Promise<void> {\n this.pendingIds.push(message.id);\n // Mark as \"sent\" immediately so it shows before the echo arrives\n this.messageStatusHandler?.(message.id, \"sent\");\n return new Promise<void>((resolve, reject) => {\n this.directLine\n .postActivity({\n type: \"message\",\n from: {\n id: this.userId,\n name: this.userName ?? this.userId,\n },\n text: (message.data as { text?: string }).text ?? \"\",\n conversation: { id: this.conversationId },\n channelId: \"directline\",\n ...(this.options.locale\n ? { locale: this.options.locale }\n : {}),\n timestamp: new Date().toISOString(),\n id: message.id,\n })\n .subscribe({\n next: () => resolve(),\n error: (err: unknown) => reject(err),\n });\n });\n }\n\n async sendFile(file: File): Promise<void> {\n const domain =\n this.options.domain ??\n \"https://directline.botframework.com/v3/directline\";\n const url = `${domain}/conversations/${this.conversationId}/upload?userId=${encodeURIComponent(this.userId)}`;\n\n const formData = new FormData();\n formData.append(\"file\", file, file.name);\n\n const res = await fetch(url, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${this.token}` },\n body: formData,\n });\n\n if (!res.ok) {\n throw new Error(`DirectLine file upload failed: ${res.status}`);\n }\n }\n\n /**\n * Submit an end-of-conversation survey as a DirectLine event activity.\n * Matches the legacy `webchat/customerfeedback` event shape so existing\n * bot flows keep working:\n * value: { rating, comment, type }\n * where `type` is `kind` coerced to a number (defaulting to 1) to preserve\n * compatibility with bots that switch on numeric survey types.\n */\n async sendSurvey(payload: SurveyPayload): Promise<void> {\n const rawType =\n typeof payload.kind === \"number\"\n ? payload.kind\n : payload.kind !== undefined\n ? Number(payload.kind)\n : 1;\n const type = Number.isFinite(rawType) ? rawType : 1;\n\n return new Promise<void>((resolve, reject) => {\n this.directLine\n .postActivity({\n type: \"event\",\n name: \"webchat/customerfeedback\",\n from: { id: this.userId, name: this.userId },\n value: {\n rating: payload.rating,\n comment: payload.comment ?? \"\",\n type,\n },\n })\n .subscribe({\n next: () => resolve(),\n error: (err: unknown) => reject(err),\n });\n });\n }\n\n async sendFeedback(\n messageId: string,\n feedback: \"like\" | \"dislike\",\n ): Promise<void> {\n // Look up the correlationId from the stored message's channelData\n const msg = this.chativaCtx?.messages\n .getAll()\n .find((m) => m.id === messageId);\n const correlationId = (\n msg?.data?.channelData as Record<string, unknown> | undefined\n )?.correlationId;\n\n if (!correlationId) {\n console.warn(\n \"[DirectLineConnector] sendFeedback: no correlationId found for message\",\n messageId,\n );\n return;\n }\n\n // Bot expects numeric: 0 = like, 1 = dislike\n const feedbackType = feedback === \"like\" ? 0 : 1;\n\n return new Promise<void>((resolve, reject) => {\n this.directLine\n .postActivity({\n type: \"event\",\n name: \"webchat/messageFeedback\",\n from: { id: this.userId, name: this.userId },\n value: { correlationId, feedbackType },\n })\n .subscribe({\n next: () => resolve(),\n error: (err: unknown) => reject(err),\n });\n });\n }\n\n async loadHistory(cursor?: string): Promise<HistoryResult> {\n const domain =\n this.options.domain ??\n \"https://directline.botframework.com/v3/directline\";\n const url = cursor\n ? `${domain}/conversations/${this.conversationId}/activities?watermark=${encodeURIComponent(cursor)}`\n : `${domain}/conversations/${this.conversationId}/activities`;\n\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${this.token}` },\n });\n\n if (!res.ok) {\n throw new Error(`DirectLine history fetch failed: ${res.status}`);\n }\n\n const data = (await res.json()) as {\n activities: Activity[];\n watermark: string;\n };\n\n const messages: IncomingMessage[] = [];\n for (const activity of data.activities) {\n // User's own messages — mapActivityToMessage filters these out (live dedup),\n // but history needs them.\n if (\n activity.from.id === this.userId &&\n activity.type === \"message\"\n ) {\n const msg = activity as Activity & { text?: string };\n if (msg.text) {\n messages.push({\n id:\n activity.id ??\n `dl-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,\n type: \"text\",\n from: \"user\",\n data: { text: msg.text },\n timestamp: activity.timestamp\n ? new Date(activity.timestamp).getTime()\n : Date.now(),\n });\n }\n continue;\n }\n\n const result = mapActivityToMessage(activity, this.userId);\n if (result !== null && result !== TYPING_SENTINEL) {\n messages.push(result);\n }\n }\n\n return {\n messages,\n hasMore: false,\n cursor: data.watermark,\n };\n }\n\n onMessage(callback: MessageHandler): void {\n this.messageHandler = callback;\n }\n\n onConnect(callback: ConnectHandler): void {\n this.connectHandler = callback;\n }\n\n onDisconnect(callback: DisconnectHandler): void {\n this.disconnectHandler = callback;\n }\n\n onTyping(callback: TypingHandler): void {\n this.typingHandler = callback;\n }\n\n onMessageStatus(callback: MessageStatusHandler): void {\n this.messageStatusHandler = callback;\n }\n\n /* ── Private helpers ───────────────────────────────────────────── */\n\n /**\n * Subscribe to DirectLine connectionStatus$ and activity$ observables.\n * Extracted so it can be re-used after an ExpiredToken reconnect.\n */\n private startListening(resolveOnOnline: boolean) {\n this.connectionSub = this.directLine.connectionStatus$.subscribe(\n (status: ConnectionStatus) => {\n switch (status) {\n case ConnectionStatus.Online:\n this.sendJoinEvent();\n // Resumed / reconnected conversations resolve immediately\n if (resolveOnOnline && this.resolveReady) {\n this.resolveReady();\n this.resolveReady = null;\n }\n break;\n case ConnectionStatus.ExpiredToken:\n this.handleExpiredToken();\n break;\n case ConnectionStatus.FailedToConnect:\n if (this.options.resumeConversation) {\n this.clearPersistedConversation();\n }\n this.disconnectHandler?.(\"Failed to connect\");\n break;\n case ConnectionStatus.Ended:\n this.disconnectHandler?.(\"Connection ended\");\n break;\n }\n },\n );\n\n this.activitySub = this.directLine.activity$.subscribe((activity) => {\n try {\n // Track watermark and conversationId from every activity\n if (activity.id) this.watermark = activity.id;\n if (!this.conversationId && activity.conversation?.id) {\n this.conversationId = activity.conversation.id;\n }\n\n // Skip own echoed activities\n if (activity.from.id === this.userId) {\n // Echoed user message → mark the original as \"read\"\n if (activity.type === \"message\") {\n const pendingId = this.pendingIds.shift();\n if (pendingId) {\n this.messageStatusHandler?.(pendingId, \"read\");\n }\n }\n return;\n }\n\n // Bot-initiated event\n if (activity.type === \"event\" && activity.name) {\n // Built-in: DisableFeedbackButton — mark the message as feedback-sent\n if (\n activity.name === \"DisableFeedbackButton\" &&\n activity.value\n ) {\n const val = activity.value as {\n CorrelationId?: string;\n FeedbackType?: number;\n };\n if (val.CorrelationId) {\n this.handleDisableFeedback(\n val.CorrelationId,\n val.FeedbackType,\n );\n }\n }\n\n // Dispatch to custom event handler (if registered)\n const handler = this.options.eventHandlers?.[activity.name];\n if (handler) {\n handler(this.createEventContext(activity));\n }\n return;\n }\n\n const result = mapActivityToMessage(activity, this.userId);\n\n if (result === TYPING_SENTINEL) {\n this.handleTyping();\n return;\n }\n\n if (result !== null) {\n // Clear typing indicator when a message arrives\n this.clearTypingTimeout();\n this.typingHandler?.(false);\n\n // First bot message → resolve connect() and signal \"connected\"\n if (this.resolveReady) {\n this.resolveReady();\n this.resolveReady = null;\n }\n\n this.messageHandler?.(result);\n\n // Persist state after delivering a message\n if (this.options.resumeConversation) {\n this.persistConversation();\n }\n }\n } catch (err) {\n console.warn(\n \"[DirectLineConnector] Activity mapping error:\",\n err,\n );\n }\n });\n }\n\n /** Build the context object passed to custom event handlers. */\n private createEventContext(activity: Activity): EventHandlerContext {\n const from = { id: this.userId, name: this.userName ?? this.userId };\n return {\n activity,\n userId: this.userId,\n userName: this.userName ?? this.userId,\n postEvent: (name: string, value?: unknown) => {\n this.directLine\n .postActivity({\n type: \"event\",\n name,\n from,\n ...(this.options.locale\n ? { locale: this.options.locale }\n : {}),\n value,\n })\n .subscribe();\n },\n chativa: this.chativaCtx!,\n };\n }\n\n /** Send webchat/join (first connect) or webchat/rejoin (reconnect) event. */\n private sendJoinEvent() {\n const locale = this.options.locale;\n const from = { id: this.userId, name: this.userName ?? this.userId };\n // Read reserved for future join-vs-rejoin branching; keeps the field alive.\n void this.hasConnectedBefore;\n\n // Skip join/rejoin when resuming a persisted conversation\n if (this._skipNextJoin) {\n this._skipNextJoin = false;\n this.hasConnectedBefore = true;\n this.directLine\n .postActivity({\n type: \"event\",\n name: \"webchat/rejoin\",\n from,\n ...(locale ? { locale } : {}),\n value: { ...(locale ? { language: locale } : {}) },\n })\n .subscribe();\n return;\n }\n this.directLine\n .postActivity({\n type: \"event\",\n name: \"webchat/join\",\n from,\n ...(locale ? { locale } : {}),\n value: {\n ...(locale ? { language: locale } : {}),\n ...this.options.joinParameters,\n },\n })\n .subscribe();\n }\n\n /** Handle DisableFeedbackButton event — find the message by correlationId and patch it. */\n private handleDisableFeedback(\n correlationId: string,\n feedbackType?: number,\n ) {\n const messages = this.chativaCtx?.messages.getAll();\n if (!messages) return;\n const msg = messages.find(\n (m) =>\n (m.data?.channelData as Record<string, unknown> | undefined)\n ?.correlationId === correlationId,\n );\n if (msg) {\n this.chativaCtx!.messages.update(msg.id, {\n data: { ...msg.data, feedbackDisabled: true, feedbackType },\n });\n }\n }\n\n private handleTyping() {\n this.clearTypingTimeout();\n this.typingHandler?.(true);\n if (this.options.typingUntilMessage) {\n // No timer — rely on next bot message (handled by ChatEngine) to clear.\n return;\n }\n const ms = this.options.typingTimeoutMs ?? 3000;\n this.typingTimeout = setTimeout(() => {\n this.typingHandler?.(false);\n this.typingTimeout = null;\n }, ms);\n }\n\n private clearTypingTimeout() {\n if (this.typingTimeout !== null) {\n clearTimeout(this.typingTimeout);\n this.typingTimeout = null;\n }\n }\n\n /* ── Token refresh ──────────────────────────────────────────────── */\n\n /** Schedule a token refresh 60 seconds before expiry. */\n private scheduleTokenRefresh() {\n this.clearRefreshTimer();\n const expiry = getTokenExpiry(this.token);\n if (!expiry) return;\n\n const delay = expiry - Date.now() - 60_000;\n if (delay <= 0) {\n // Token is already about to expire — refresh immediately\n this.refreshTokenNow();\n return;\n }\n this.refreshTimer = setTimeout(() => this.refreshTokenNow(), delay);\n }\n\n /** Pre-emptively refresh the token before it expires. */\n private async refreshTokenNow() {\n try {\n const result = await refreshDirectLineToken(\n this.token,\n this.options.domain,\n );\n this.token = result.token;\n this.scheduleTokenRefresh();\n if (this.options.resumeConversation) {\n this.persistConversation();\n }\n } catch (err) {\n console.warn(\"[DirectLineConnector] Token refresh failed:\", err);\n }\n }\n\n /**\n * Called when DirectLine emits ExpiredToken status.\n * Refreshes the token and recreates the DirectLine connection.\n */\n private async handleExpiredToken() {\n try {\n const result = await refreshDirectLineToken(\n this.token,\n this.options.domain,\n );\n this.token = result.token;\n this.scheduleTokenRefresh();\n } catch {\n if (this.options.resumeConversation) {\n this.clearPersistedConversation();\n }\n this.disconnectHandler?.(\"Token expired and refresh failed\");\n return;\n }\n\n // Tear down old DirectLine\n this.activitySub?.unsubscribe();\n this.connectionSub?.unsubscribe();\n this.clearTypingTimeout();\n try {\n this.directLine.end();\n } catch {\n /* already ended */\n }\n\n // Recreate with new token, preserving conversation\n this.directLine = new DirectLine({\n token: this.token,\n domain: this.options.domain,\n conversationId: this.conversationId,\n watermark: this.watermark,\n });\n\n this.startListening(true);\n\n if (this.options.resumeConversation) {\n this.persistConversation();\n }\n }\n\n private clearRefreshTimer() {\n if (this.refreshTimer !== null) {\n clearTimeout(this.refreshTimer);\n this.refreshTimer = null;\n }\n }\n\n /* ── Conversation persistence ───────────────────────────────────── */\n\n private persistConversation() {\n if (!this.conversationId || !this.token) return;\n try {\n const data: PersistedConversation = {\n conversationId: this.conversationId,\n token: this.token,\n watermark: this.watermark,\n userId: this.userId,\n };\n localStorage.setItem(CONVERSATION_KEY, JSON.stringify(data));\n } catch {\n // localStorage unavailable\n }\n }\n\n private loadPersistedConversation(): PersistedConversation | null {\n try {\n const raw = localStorage.getItem(CONVERSATION_KEY);\n if (!raw) return null;\n return JSON.parse(raw) as PersistedConversation;\n } catch {\n return null;\n }\n }\n\n private clearPersistedConversation() {\n try {\n localStorage.removeItem(CONVERSATION_KEY);\n } catch {\n // best-effort\n }\n }\n}\n"],"names":["TYPING_SENTINEL","CT_HERO","CT_THUMBNAIL","CT_ADAPTIVE","CT_SIGNIN","CT_OAUTH","CT_RECEIPT","CT_AUDIO","CT_VIDEO","CT_ANIMATION","CT_FLEX","mapActivityToMessage","activity","userId","msg","id","timestamp","channelData","suggestedActions","mapSuggestedActions","result","mapAttachments","attachments","layout","cardTypes","adaptiveCardToCardData","mapHeroLikeCard","mapSingleAttachment","att","ct","content","mapAdaptiveCard","mapCardButtons","mapReceiptCard","mediaUrl","buttons","btn","label","actions","a","walkAdaptiveElements","elements","texts","onImage","el","mapAdaptiveActions","col","parseAdaptiveCardBody","image","url","fallback","out","lines","fact","item","price","USER_ID_KEY","CONVERSATION_KEY","getOrCreateUserId","stored","getTokenExpiry","token","payload","fetchToken","secret","res","data","fetchTokenFromUrl","refreshDirectLineToken","currentToken","domain","DirectLineConnector","options","ctx","name","handler","isResuming","persisted","refreshed","DirectLine","ready","resolve","message","reject","err","file","formData","rawType","type","messageId","feedback","correlationId","m","feedbackType","cursor","messages","callback","resolveOnOnline","status","ConnectionStatus","pendingId","val","from","value","locale","ms","expiry","delay","raw"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/mapActivity.ts","../src/DirectLineConnector.ts"],"sourcesContent":["/**\n * Pure mapping functions that convert DirectLine activities\n * into Chativa IncomingMessage structures.\n *\n * No side-effects — all functions are stateless and easily testable.\n */\n\nimport type {\n Activity,\n Message,\n CardAction,\n Attachment,\n HeroCard,\n Thumbnail,\n Signin,\n Receipt,\n AudioCard,\n VideoCard,\n AnimationCard,\n AdaptiveCard,\n FlexCard,\n} from \"botframework-directlinejs\";\nimport type { IncomingMessage, MessageAction } from \"@chativa/core\";\n\n/* ------------------------------------------------------------------ */\n/* Sentinel returned for typing activities */\n/* ------------------------------------------------------------------ */\n\nexport const TYPING_SENTINEL = Symbol(\"typing\");\nexport type MapResult = IncomingMessage | typeof TYPING_SENTINEL | null;\n\n/* ------------------------------------------------------------------ */\n/* Content-type constants */\n/* ------------------------------------------------------------------ */\n\nconst CT_HERO = \"application/vnd.microsoft.card.hero\";\nconst CT_THUMBNAIL = \"application/vnd.microsoft.card.thumbnail\";\nconst CT_ADAPTIVE = \"application/vnd.microsoft.card.adaptive\";\nconst CT_SIGNIN = \"application/vnd.microsoft.card.signin\";\nconst CT_OAUTH = \"application/vnd.microsoft.card.oauth\";\nconst CT_RECEIPT = \"application/vnd.microsoft.card.receipt\";\nconst CT_AUDIO = \"application/vnd.microsoft.card.audio\";\nconst CT_VIDEO = \"application/vnd.microsoft.card.video\";\nconst CT_ANIMATION = \"application/vnd.microsoft.card.animation\";\nconst CT_FLEX = \"application/vnd.microsoft.card.flex\";\n\n/* ------------------------------------------------------------------ */\n/* Main entry point */\n/* ------------------------------------------------------------------ */\n\n/**\n * Convert a DirectLine Activity into a Chativa IncomingMessage.\n *\n * Returns:\n * - `IncomingMessage` for renderable messages\n * - `TYPING_SENTINEL` for typing indicators (handled by the connector)\n * - `null` for activities that should be ignored (echo, events, etc.)\n */\nexport function mapActivityToMessage(\n activity: Activity,\n userId: string,\n): MapResult {\n // Filter out echoed user messages\n if (activity.from.id === userId) return null;\n\n // Typing indicator\n if (activity.type === \"typing\") return TYPING_SENTINEL;\n\n // Only process message activities\n if (activity.type !== \"message\") return null;\n\n const msg = activity as Message;\n const id = msg.id ?? `dl-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n const timestamp = msg.timestamp ? new Date(msg.timestamp).getTime() : Date.now();\n\n // Preserve channelData (e.g. correlationId used for feedback)\n const channelData = (msg as unknown as { channelData?: Record<string, unknown> }).channelData;\n\n // Map suggested actions (may be used as top-level actions or as quick-reply)\n const suggestedActions = mapSuggestedActions(msg);\n\n // If there are attachments, process them\n if (msg.attachments && msg.attachments.length > 0) {\n const result = mapAttachments(msg, id, timestamp);\n if (result) {\n if (suggestedActions.length > 0) result.actions = suggestedActions;\n if (channelData) result.data.channelData = channelData;\n }\n return result;\n }\n\n // Text + suggested actions → quick-reply\n if (suggestedActions.length > 0) {\n return {\n id,\n type: \"quick-reply\",\n from: \"bot\",\n data: { text: msg.text ?? \"\", actions: suggestedActions, ...(channelData ? { channelData } : {}) },\n timestamp,\n };\n }\n\n // Plain text\n if (msg.text) {\n return {\n id,\n type: \"text\",\n from: \"bot\",\n data: { text: msg.text, ...(channelData ? { channelData } : {}) },\n timestamp,\n };\n }\n\n // Nothing meaningful\n return null;\n}\n\n/* ------------------------------------------------------------------ */\n/* Attachment mapping */\n/* ------------------------------------------------------------------ */\n\nfunction mapAttachments(\n msg: Message,\n id: string,\n timestamp: number,\n): IncomingMessage | null {\n const attachments = msg.attachments!;\n const layout = msg.attachmentLayout;\n\n // Multiple cards with carousel layout\n const cardTypes = [CT_HERO, CT_THUMBNAIL, CT_FLEX, CT_ADAPTIVE];\n const allCards = attachments.every((a) => cardTypes.includes(a.contentType));\n\n if (allCards && (attachments.length > 1 || layout === \"carousel\")) {\n return {\n id,\n type: \"carousel\",\n from: \"bot\",\n data: {\n cards: attachments.map((a) => {\n if (a.contentType === CT_ADAPTIVE) {\n return adaptiveCardToCardData(\n (a as AdaptiveCard).content as Record<string, unknown>,\n );\n }\n return mapHeroLikeCard((a as HeroCard | Thumbnail | FlexCard).content);\n }),\n },\n timestamp,\n };\n }\n\n // Single attachment\n return mapSingleAttachment(attachments[0], msg, id, timestamp);\n}\n\nfunction mapSingleAttachment(\n att: Attachment,\n msg: Message,\n id: string,\n timestamp: number,\n): IncomingMessage | null {\n const ct = att.contentType;\n\n // Hero / Thumbnail / Flex card\n if (ct === CT_HERO || ct === CT_THUMBNAIL || ct === CT_FLEX) {\n const content = (att as HeroCard | Thumbnail | FlexCard).content;\n return {\n id,\n type: \"card\",\n from: \"bot\",\n data: mapHeroLikeCard(content),\n timestamp,\n };\n }\n\n // Adaptive card — simple parse\n if (ct === CT_ADAPTIVE) {\n return mapAdaptiveCard((att as AdaptiveCard).content, id, timestamp);\n }\n\n // Signin / OAuth card\n if (ct === CT_SIGNIN || ct === CT_OAUTH) {\n const content = (att as Signin).content;\n return {\n id,\n type: \"buttons\",\n from: \"bot\",\n data: {\n text: content.text ?? \"Please sign in\",\n buttons: mapCardButtons(content.buttons),\n },\n timestamp,\n };\n }\n\n // Receipt card\n if (ct === CT_RECEIPT) {\n return mapReceiptCard((att as Receipt).content, id, timestamp);\n }\n\n // Video card\n if (ct === CT_VIDEO) {\n const content = (att as VideoCard).content;\n const mediaUrl = content.media?.[0]?.url;\n if (!mediaUrl) return null;\n return {\n id,\n type: \"video\",\n from: \"bot\",\n data: {\n src: mediaUrl,\n poster: content.image?.url,\n caption: content.title ?? msg.text,\n },\n timestamp,\n };\n }\n\n // Audio card\n if (ct === CT_AUDIO) {\n const content = (att as AudioCard).content;\n const mediaUrl = content.media?.[0]?.url;\n if (!mediaUrl) return null;\n return {\n id,\n type: \"file\",\n from: \"bot\",\n data: {\n url: mediaUrl,\n name: content.title ?? \"audio\",\n mimeType: \"audio/mpeg\",\n },\n timestamp,\n };\n }\n\n // Animation card (typically GIFs)\n if (ct === CT_ANIMATION) {\n const content = (att as AnimationCard).content;\n const mediaUrl = content.media?.[0]?.url;\n if (!mediaUrl) return null;\n return {\n id,\n type: \"image\",\n from: \"bot\",\n data: {\n src: mediaUrl,\n caption: content.title ?? msg.text,\n },\n timestamp,\n };\n }\n\n // Image attachment (contentType starts with \"image/\")\n if (ct.startsWith(\"image/\") && \"contentUrl\" in att) {\n return {\n id,\n type: \"image\",\n from: \"bot\",\n data: {\n src: att.contentUrl,\n alt: att.name,\n caption: msg.text,\n },\n timestamp,\n };\n }\n\n // Video file attachment\n if (ct.startsWith(\"video/\") && \"contentUrl\" in att) {\n return {\n id,\n type: \"video\",\n from: \"bot\",\n data: {\n src: att.contentUrl,\n caption: msg.text,\n },\n timestamp,\n };\n }\n\n // Generic file attachment\n if (\"contentUrl\" in att) {\n return {\n id,\n type: \"file\",\n from: \"bot\",\n data: {\n url: att.contentUrl,\n name: att.name ?? \"file\",\n mimeType: ct,\n },\n timestamp,\n };\n }\n\n return null;\n}\n\n/* ------------------------------------------------------------------ */\n/* Hero-like card mapping (hero, thumbnail, flex share same shape) */\n/* ------------------------------------------------------------------ */\n\nfunction mapHeroLikeCard(content: HeroCard[\"content\"]): Record<string, unknown> {\n return {\n image: content.images?.[0]?.url,\n title: content.title ?? \"\",\n subtitle: content.subtitle ?? content.text,\n buttons: mapCardButtons(content.buttons),\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Card button / action mapping */\n/* ------------------------------------------------------------------ */\n\nexport function mapCardButtons(\n buttons?: CardAction[],\n): MessageAction[] {\n if (!buttons || buttons.length === 0) return [];\n\n return buttons.map((btn): MessageAction => {\n const label = (\"title\" in btn ? btn.title : undefined) ?? String(btn.value ?? \"\");\n\n switch (btn.type) {\n case \"openUrl\":\n case \"signin\":\n return { label, url: String(btn.value ?? \"\") };\n\n case \"call\":\n return { label, url: String(btn.value ?? \"\") };\n\n case \"imBack\":\n case \"postBack\":\n case \"messageBack\":\n default:\n return { label, value: String(btn.value ?? label) };\n }\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Suggested actions mapping */\n/* ------------------------------------------------------------------ */\n\nfunction mapSuggestedActions(msg: Message): MessageAction[] {\n const actions = msg.suggestedActions?.actions;\n if (!actions || actions.length === 0) return [];\n\n return actions.map((a): MessageAction => {\n const label = (\"title\" in a ? a.title : undefined) ?? String(a.value ?? \"\");\n if (a.type === \"openUrl\") {\n return { label, url: String(a.value ?? \"\") };\n }\n return { label, value: String(a.value ?? label) };\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* Adaptive Card — simple parse */\n/* ------------------------------------------------------------------ */\n\ninterface AdaptiveElement {\n type: string;\n text?: string;\n url?: string;\n body?: AdaptiveElement[];\n items?: AdaptiveElement[];\n columns?: Array<{ items?: AdaptiveElement[] }>;\n actions?: Array<{ type: string; title?: string; url?: string; data?: unknown }>;\n [key: string]: unknown;\n}\n\n/** Recursively walk Adaptive Card elements and collect texts, the first image, and buttons. */\nfunction walkAdaptiveElements(\n elements: AdaptiveElement[] | undefined,\n texts: string[],\n buttons: MessageAction[],\n onImage: (url: string) => void,\n) {\n if (!elements) return;\n for (const el of elements) {\n switch (el.type) {\n case \"TextBlock\":\n if (el.text) texts.push(el.text);\n break;\n case \"Image\":\n if (el.url) onImage(el.url);\n break;\n case \"ActionSet\":\n if (el.actions) mapAdaptiveActions(el.actions, buttons);\n break;\n case \"Container\":\n walkAdaptiveElements(el.items, texts, buttons, onImage);\n break;\n case \"ColumnSet\":\n for (const col of el.columns ?? []) {\n walkAdaptiveElements(col.items, texts, buttons, onImage);\n }\n break;\n case \"Column\":\n walkAdaptiveElements(el.items, texts, buttons, onImage);\n break;\n }\n }\n}\n\n/** Parse an Adaptive Card body into { image, title, subtitle, buttons }. */\nfunction parseAdaptiveCardBody(content: Record<string, unknown>) {\n const texts: string[] = [];\n let image: string | undefined;\n const buttons: MessageAction[] = [];\n\n walkAdaptiveElements(\n content.body as AdaptiveElement[] | undefined,\n texts,\n buttons,\n (url) => { image = image ?? url; },\n );\n\n if (Array.isArray(content.actions)) {\n mapAdaptiveActions(content.actions as AdaptiveElement[\"actions\"] & object, buttons);\n }\n\n return { texts, image, buttons };\n}\n\n/**\n * Extract card-like data from an Adaptive Card — used inside carousels.\n */\nfunction adaptiveCardToCardData(\n content: Record<string, unknown>,\n): Record<string, unknown> {\n const { texts, image, buttons } = parseAdaptiveCardBody(content);\n return {\n image,\n title: texts[0] ?? \"\",\n subtitle: texts.slice(1).join(\"\\n\"),\n buttons,\n };\n}\n\nfunction mapAdaptiveCard(\n content: Record<string, unknown>,\n id: string,\n timestamp: number,\n): IncomingMessage {\n const { texts, image, buttons } = parseAdaptiveCardBody(content);\n\n // Fallback text\n const fallback =\n (content.fallbackText as string) ??\n (content.speak as string) ??\n texts.join(\"\\n\");\n\n // If we have an image and a title, render as card\n if (image) {\n return {\n id,\n type: \"card\",\n from: \"bot\",\n data: {\n image,\n title: texts[0] ?? \"\",\n subtitle: texts.slice(1).join(\"\\n\"),\n buttons,\n },\n timestamp,\n };\n }\n\n // If we have buttons, render as buttons message\n if (buttons.length > 0) {\n return {\n id,\n type: \"buttons\",\n from: \"bot\",\n data: {\n text: fallback || \"Adaptive Card\",\n buttons,\n },\n timestamp,\n };\n }\n\n // Plain text fallback\n return {\n id,\n type: \"text\",\n from: \"bot\",\n data: { text: fallback || \"[Adaptive Card]\" },\n timestamp,\n };\n}\n\nfunction mapAdaptiveActions(\n actions: Array<{ type: string; title?: string; url?: string; data?: unknown }>,\n out: MessageAction[],\n) {\n for (const a of actions) {\n const label = a.title ?? \"Action\";\n if (a.type === \"Action.OpenUrl\" && a.url) {\n out.push({ label, url: a.url });\n } else if (a.type === \"Action.Submit\") {\n out.push({ label, value: typeof a.data === \"string\" ? a.data : label });\n } else {\n out.push({ label, value: label });\n }\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* Receipt card mapping */\n/* ------------------------------------------------------------------ */\n\nfunction mapReceiptCard(\n content: Receipt[\"content\"],\n id: string,\n timestamp: number,\n): IncomingMessage {\n const lines: string[] = [];\n if (content.title) lines.push(`**${content.title}**`);\n\n if (content.facts) {\n for (const fact of content.facts) {\n lines.push(`${fact.key}: ${fact.value}`);\n }\n }\n\n if (content.items) {\n for (const item of content.items) {\n const price = item.price ? ` — ${item.price}` : \"\";\n lines.push(`- ${item.title ?? \"Item\"}${price}`);\n }\n }\n\n if (content.tax) lines.push(`Tax: ${content.tax}`);\n if (content.total) lines.push(`**Total: ${content.total}**`);\n\n return {\n id,\n type: \"text\",\n from: \"bot\",\n data: { text: lines.join(\"\\n\") },\n timestamp,\n };\n}\n","import type {\n IConnector,\n MessageHandler,\n ConnectHandler,\n DisconnectHandler,\n TypingHandler,\n MessageStatusHandler,\n ChativaContext,\n SurveyPayload,\n} from \"@chativa/core\";\nimport type {\n OutgoingMessage,\n HistoryResult,\n IncomingMessage,\n} from \"@chativa/core\";\nimport { DirectLine, ConnectionStatus } from \"botframework-directlinejs\";\nimport type { Activity } from \"botframework-directlinejs\";\nimport { mapActivityToMessage, TYPING_SENTINEL } from \"./mapActivity\";\n\n/** Minimal subscription interface returned by RxJS5 Observable.subscribe(). */\ninterface Unsubscribable {\n unsubscribe(): void;\n}\n\n/**\n * Context passed to custom event handlers — provides the info and methods\n * needed to respond to a bot-initiated event activity.\n */\nexport interface EventHandlerContext {\n /** The raw DirectLine event activity. */\n activity: Activity;\n /** The user ID for this session. */\n userId: string;\n /** The user display name for this session. */\n userName: string;\n /** Send an event activity back to the bot. */\n postEvent(name: string, value?: unknown): void;\n /**\n * Full Chativa context — access messages, chat UI, theme, and event bus.\n * Available when the connector is used via ChatEngine (which injects it).\n */\n chativa: ChativaContext;\n}\n\n/**\n * Handler for a bot-initiated event activity.\n * Keyed by event name (e.g. `\"LocationRequest\"`).\n */\nexport type EventHandler = (ctx: EventHandlerContext) => void;\n\nexport interface DirectLineConnectorOptions {\n /** DirectLine channel secret (server-side only — generates a token). */\n secret?: string;\n /** Pre-fetched DirectLine token. */\n token?: string;\n /** URL of a custom token-generating endpoint (POST, returns { token, conversationId? }). */\n tokenGeneratorUrl?: string;\n /**\n * Override the user ID. When omitted, a random per-instance ID is\n * generated — unless `resumeConversation` is true, in which case the ID\n * is persisted to localStorage so reloads can rejoin the same\n * conversation.\n */\n userId?: string;\n /** Display name sent with activities. Defaults to the (resolved) userId. */\n userName?: string;\n /** Sovereign-cloud DirectLine endpoint (e.g. government, china). */\n domain?: string;\n /** BCP-47 locale sent with the webchat/join event and outgoing activities (e.g. \"tr-TR\"). */\n locale?: string;\n /**\n * Extra key-value pairs merged into the `webchat/join` event's `value` payload.\n * Example: `{ language: \"tr\", tenant: \"galataport\" }`\n */\n joinParameters?: Record<string, unknown>;\n /**\n * Custom handlers for bot-initiated event activities, keyed by event name.\n * Example:\n * ```ts\n * eventHandlers: {\n * LocationRequest: (ctx) => {\n * navigator.geolocation.getCurrentPosition((pos) => {\n * ctx.postEvent(\"webchat/location\", {\n * latitude: pos.coords.latitude,\n * longitude: pos.coords.longitude,\n * });\n * });\n * },\n * }\n * ```\n */\n eventHandlers?: Record<string, EventHandler>;\n /**\n * When true, persist conversation state (conversationId, token, watermark)\n * and the auto-generated userId to localStorage so the conversation can\n * be resumed across page reloads. Default: `false` — each new connector\n * instance gets a fresh userId and opens a new conversation.\n */\n resumeConversation?: boolean;\n /**\n * How long (ms) to keep the typing indicator visible after a bot typing\n * signal before auto-clearing it. Each new typing signal resets the timer.\n * Default: 3000. Ignored when `typingUntilMessage` is true.\n */\n typingTimeoutMs?: number;\n /**\n * When true, the typing indicator stays on until the next bot message\n * arrives (no auto-clear timeout).\n */\n typingUntilMessage?: boolean;\n}\n\n/* ── Constants ────────────────────────────────────────────────────── */\n\nconst USER_ID_KEY = \"chativa_directline_userId\";\nconst CONVERSATION_KEY = \"chativa_directline_conversation\";\n\ninterface PersistedConversation {\n conversationId: string;\n token: string;\n watermark?: string;\n userId: string;\n}\n\n/* ── Module-level helpers ─────────────────────────────────────────── */\n\nfunction randomUserId(): string {\n return (\n Math.random().toString(36).slice(2, 15) +\n Math.random().toString(36).slice(2, 15)\n );\n}\n\n/** Read a persisted userId for conversation-resume mode, generating and\n * storing one on first use. Only called when `resumeConversation` is true. */\nfunction getOrCreateUserId(): string {\n try {\n const stored = localStorage.getItem(USER_ID_KEY);\n if (stored) return stored;\n } catch {\n // localStorage unavailable (e.g. incognito, SSR)\n }\n const id = randomUserId();\n try {\n localStorage.setItem(USER_ID_KEY, id);\n } catch {\n // best-effort\n }\n return id;\n}\n\n/** Extract expiry time (ms since epoch) from a JWT token. */\nfunction getTokenExpiry(token: string): number | null {\n try {\n const payload = JSON.parse(atob(token.split(\".\")[1]));\n return typeof payload.exp === \"number\" ? payload.exp * 1000 : null;\n } catch {\n return null;\n }\n}\n\nasync function fetchToken(\n secret: string,\n userId: string,\n): Promise<{ token: string; conversationId: string }> {\n const res = await fetch(\n \"https://directline.botframework.com/v3/directline/tokens/generate\",\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${secret}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ user: { id: userId, name: userId } }),\n },\n );\n if (!res.ok) {\n throw new Error(`DirectLine token fetch failed: ${res.status}`);\n }\n const data = (await res.json()) as {\n token: string;\n conversationId: string;\n };\n return { token: data.token, conversationId: data.conversationId };\n}\n\nasync function fetchTokenFromUrl(\n url: string,\n): Promise<{ token: string; conversationId?: string; userId?: string }> {\n const res = await fetch(url, { method: \"POST\" });\n if (!res.ok) {\n throw new Error(`Token generator failed: ${res.status}`);\n }\n return (await res.json()) as {\n token: string;\n conversationId?: string;\n userId?: string;\n };\n}\n\n/** Refresh an existing DirectLine token via the REST API. */\nasync function refreshDirectLineToken(\n currentToken: string,\n domain?: string,\n): Promise<{ token: string; conversationId: string }> {\n const base = domain ?? \"https://directline.botframework.com/v3/directline\";\n const res = await fetch(`${base}/tokens/refresh`, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${currentToken}` },\n });\n if (!res.ok) {\n throw new Error(`Token refresh failed: ${res.status}`);\n }\n return (await res.json()) as { token: string; conversationId: string };\n}\n\n/**\n * DirectLineConnector — Azure Bot Framework DirectLine v3 adapter.\n *\n * Maps all Bot Framework activity types (hero cards, carousels,\n * suggested actions, images, videos, files, adaptive cards, etc.)\n * into Chativa's native message types.\n */\nexport class DirectLineConnector implements IConnector {\n readonly name = \"directline\";\n readonly addSentToHistory = true;\n\n private directLine!: DirectLine;\n private conversationId!: string;\n private userId!: string;\n private userName: string | undefined;\n private token!: string;\n private options: DirectLineConnectorOptions;\n private chativaCtx: ChativaContext | null = null;\n\n private messageHandler: MessageHandler | null = null;\n private connectHandler: ConnectHandler | null = null;\n private disconnectHandler: DisconnectHandler | null = null;\n private typingHandler: TypingHandler | null = null;\n private messageStatusHandler: MessageStatusHandler | null = null;\n\n private activitySub: Unsubscribable | null = null;\n private connectionSub: Unsubscribable | null = null;\n private typingTimeout: ReturnType<typeof setTimeout> | null = null;\n private refreshTimer: ReturnType<typeof setTimeout> | null = null;\n /** Queue of sent message IDs awaiting echo confirmation. */\n private pendingIds: string[] = [];\n /** True after the first successful connection (reserved for future join-vs-rejoin logic). */\n private hasConnectedBefore = false;\n /** Resolves the connect() promise once the bot sends its first message after join. */\n private resolveReady: (() => void) | null = null;\n /** Last known activity watermark — used for conversation resume. */\n private watermark: string | undefined;\n /** When true, skip the next join/rejoin event (used during resume). */\n private _skipNextJoin = false;\n\n constructor(options: DirectLineConnectorOptions) {\n this.options = options;\n }\n\n setContext(ctx: ChativaContext): void {\n this.chativaCtx = ctx;\n }\n\n /**\n * Register (or replace) an event handler for a bot-initiated event activity.\n * Can be called before or after `connect()`.\n *\n * @example\n * ```ts\n * connector.addEventHandler(\"LocationRequest\", (ctx) => {\n * navigator.geolocation.getCurrentPosition((pos) => {\n * ctx.postEvent(\"webchat/location\", { latitude: pos.coords.latitude, ... });\n * });\n * });\n * ```\n */\n addEventHandler(name: string, handler: EventHandler): void {\n this.options.eventHandlers ??= {};\n this.options.eventHandlers[name] = handler;\n }\n\n /** Remove a previously registered event handler by name. */\n removeEventHandler(name: string): boolean {\n if (!this.options.eventHandlers?.[name]) return false;\n delete this.options.eventHandlers[name];\n return true;\n }\n\n /** Check whether an event handler is registered for the given name. */\n hasEventHandler(name: string): boolean {\n return !!this.options.eventHandlers?.[name];\n }\n\n /** Return the names of all registered event handlers. */\n getEventHandlerNames(): string[] {\n return Object.keys(this.options.eventHandlers ?? {});\n }\n\n async connect(): Promise<void> {\n this.userId =\n this.options.userId ??\n (this.options.resumeConversation\n ? getOrCreateUserId()\n : randomUserId());\n this.userName = this.options.userName;\n\n // ── Try to resume a persisted conversation ────────────────────\n let isResuming = false;\n if (this.options.resumeConversation) {\n const persisted = this.loadPersistedConversation();\n if (persisted) {\n try {\n const refreshed = await refreshDirectLineToken(\n persisted.token,\n this.options.domain,\n );\n this.token = refreshed.token;\n this.conversationId = persisted.conversationId;\n this.watermark = persisted.watermark;\n this.userId = persisted.userId;\n isResuming = true;\n } catch {\n // Persisted token expired or invalid — start fresh\n this.clearPersistedConversation();\n }\n }\n }\n\n // ── Acquire token (fresh conversation) ────────────────────────\n if (!isResuming) {\n if (this.options.tokenGeneratorUrl) {\n const result = await fetchTokenFromUrl(\n this.options.tokenGeneratorUrl,\n );\n this.token = result.token;\n if (result.conversationId)\n this.conversationId = result.conversationId;\n if (result.userId) this.userId = result.userId;\n } else if (this.options.token) {\n this.token = this.options.token;\n } else if (this.options.secret) {\n const result = await fetchToken(\n this.options.secret,\n this.userId,\n );\n this.token = result.token;\n this.conversationId = result.conversationId;\n } else {\n throw new Error(\n \"DirectLineConnector: provide token, secret, or tokenGeneratorUrl.\",\n );\n }\n }\n\n // ── Schedule automatic token refresh ──────────────────────────\n this.scheduleTokenRefresh();\n\n // ── Create DirectLine instance ────────────────────────────────\n this.directLine = new DirectLine({\n token: this.token,\n domain: this.options.domain,\n ...(isResuming\n ? {\n conversationId: this.conversationId,\n watermark: this.watermark,\n }\n : {}),\n });\n\n if (isResuming) {\n this.hasConnectedBefore = true;\n this._skipNextJoin = true;\n }\n\n // ── Wait for connection ───────────────────────────────────────\n const ready = new Promise<void>((resolve) => {\n this.resolveReady = resolve;\n });\n\n this.startListening(isResuming);\n\n await ready;\n this.connectHandler?.();\n\n if (this.options.resumeConversation) {\n this.persistConversation();\n }\n }\n\n async disconnect(): Promise<void> {\n this.activitySub?.unsubscribe();\n this.activitySub = null;\n this.connectionSub?.unsubscribe();\n this.connectionSub = null;\n this.clearTypingTimeout();\n this.clearRefreshTimer();\n\n try {\n this.directLine?.end();\n } catch {\n // DirectLine.end() may throw if already ended\n }\n\n this.messageHandler = null;\n this.connectHandler = null;\n this.disconnectHandler = null;\n this.typingHandler = null;\n this.messageStatusHandler = null;\n }\n\n /** Clear persisted conversation state and reset watermark. */\n clearConversation(): void {\n this.watermark = undefined;\n this.clearPersistedConversation();\n }\n\n async sendMessage(message: OutgoingMessage): Promise<void> {\n this.pendingIds.push(message.id);\n // Mark as \"sent\" immediately so it shows before the echo arrives\n this.messageStatusHandler?.(message.id, \"sent\");\n return new Promise<void>((resolve, reject) => {\n this.directLine\n .postActivity({\n type: \"message\",\n from: {\n id: this.userId,\n name: this.userName ?? this.userId,\n },\n text: (message.data as { text?: string }).text ?? \"\",\n conversation: { id: this.conversationId },\n channelId: \"directline\",\n ...(this.options.locale\n ? { locale: this.options.locale }\n : {}),\n timestamp: new Date().toISOString(),\n id: message.id,\n })\n .subscribe({\n next: () => resolve(),\n error: (err: unknown) => reject(err),\n });\n });\n }\n\n async sendFile(file: File): Promise<void> {\n const domain =\n this.options.domain ??\n \"https://directline.botframework.com/v3/directline\";\n const url = `${domain}/conversations/${this.conversationId}/upload?userId=${encodeURIComponent(this.userId)}`;\n\n const formData = new FormData();\n formData.append(\"file\", file, file.name);\n\n const res = await fetch(url, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${this.token}` },\n body: formData,\n });\n\n if (!res.ok) {\n throw new Error(`DirectLine file upload failed: ${res.status}`);\n }\n }\n\n /**\n * Submit an end-of-conversation survey as a DirectLine event activity.\n * Matches the legacy `webchat/customerfeedback` event shape so existing\n * bot flows keep working:\n * value: { rating, comment, type }\n * where `type` is `kind` coerced to a number (defaulting to 1) to preserve\n * compatibility with bots that switch on numeric survey types.\n */\n async sendSurvey(payload: SurveyPayload): Promise<void> {\n const rawType =\n typeof payload.kind === \"number\"\n ? payload.kind\n : payload.kind !== undefined\n ? Number(payload.kind)\n : 1;\n const type = Number.isFinite(rawType) ? rawType : 1;\n\n return new Promise<void>((resolve, reject) => {\n this.directLine\n .postActivity({\n type: \"event\",\n name: \"webchat/customerfeedback\",\n from: { id: this.userId, name: this.userId },\n value: {\n rating: payload.rating,\n comment: payload.comment ?? \"\",\n type,\n },\n })\n .subscribe({\n next: () => resolve(),\n error: (err: unknown) => reject(err),\n });\n });\n }\n\n async sendFeedback(\n messageId: string,\n feedback: \"like\" | \"dislike\",\n ): Promise<void> {\n // Look up the correlationId from the stored message's channelData\n const msg = this.chativaCtx?.messages\n .getAll()\n .find((m) => m.id === messageId);\n const correlationId = (\n msg?.data?.channelData as Record<string, unknown> | undefined\n )?.correlationId;\n\n if (!correlationId) {\n console.warn(\n \"[DirectLineConnector] sendFeedback: no correlationId found for message\",\n messageId,\n );\n return;\n }\n\n // Bot expects numeric: 0 = like, 1 = dislike\n const feedbackType = feedback === \"like\" ? 0 : 1;\n\n return new Promise<void>((resolve, reject) => {\n this.directLine\n .postActivity({\n type: \"event\",\n name: \"webchat/messageFeedback\",\n from: { id: this.userId, name: this.userId },\n value: { correlationId, feedbackType },\n })\n .subscribe({\n next: () => resolve(),\n error: (err: unknown) => reject(err),\n });\n });\n }\n\n async loadHistory(cursor?: string): Promise<HistoryResult> {\n const domain =\n this.options.domain ??\n \"https://directline.botframework.com/v3/directline\";\n const url = cursor\n ? `${domain}/conversations/${this.conversationId}/activities?watermark=${encodeURIComponent(cursor)}`\n : `${domain}/conversations/${this.conversationId}/activities`;\n\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${this.token}` },\n });\n\n if (!res.ok) {\n throw new Error(`DirectLine history fetch failed: ${res.status}`);\n }\n\n const data = (await res.json()) as {\n activities: Activity[];\n watermark: string;\n };\n\n const messages: IncomingMessage[] = [];\n for (const activity of data.activities) {\n // User's own messages — mapActivityToMessage filters these out (live dedup),\n // but history needs them.\n if (\n activity.from.id === this.userId &&\n activity.type === \"message\"\n ) {\n const msg = activity as Activity & { text?: string };\n if (msg.text) {\n messages.push({\n id:\n activity.id ??\n `dl-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,\n type: \"text\",\n from: \"user\",\n data: { text: msg.text },\n timestamp: activity.timestamp\n ? new Date(activity.timestamp).getTime()\n : Date.now(),\n });\n }\n continue;\n }\n\n const result = mapActivityToMessage(activity, this.userId);\n if (result !== null && result !== TYPING_SENTINEL) {\n messages.push(result);\n }\n }\n\n return {\n messages,\n hasMore: false,\n cursor: data.watermark,\n };\n }\n\n onMessage(callback: MessageHandler): void {\n this.messageHandler = callback;\n }\n\n onConnect(callback: ConnectHandler): void {\n this.connectHandler = callback;\n }\n\n onDisconnect(callback: DisconnectHandler): void {\n this.disconnectHandler = callback;\n }\n\n onTyping(callback: TypingHandler): void {\n this.typingHandler = callback;\n }\n\n onMessageStatus(callback: MessageStatusHandler): void {\n this.messageStatusHandler = callback;\n }\n\n /* ── Private helpers ───────────────────────────────────────────── */\n\n /**\n * Subscribe to DirectLine connectionStatus$ and activity$ observables.\n * Extracted so it can be re-used after an ExpiredToken reconnect.\n */\n private startListening(resolveOnOnline: boolean) {\n this.connectionSub = this.directLine.connectionStatus$.subscribe(\n (status: ConnectionStatus) => {\n switch (status) {\n case ConnectionStatus.Online:\n this.sendJoinEvent();\n // Resumed / reconnected conversations resolve immediately\n if (resolveOnOnline && this.resolveReady) {\n this.resolveReady();\n this.resolveReady = null;\n }\n break;\n case ConnectionStatus.ExpiredToken:\n this.handleExpiredToken();\n break;\n case ConnectionStatus.FailedToConnect:\n if (this.options.resumeConversation) {\n this.clearPersistedConversation();\n }\n this.disconnectHandler?.(\"Failed to connect\");\n break;\n case ConnectionStatus.Ended:\n this.disconnectHandler?.(\"Connection ended\");\n break;\n }\n },\n );\n\n this.activitySub = this.directLine.activity$.subscribe((activity) => {\n try {\n // Track watermark and conversationId from every activity\n if (activity.id) this.watermark = activity.id;\n if (!this.conversationId && activity.conversation?.id) {\n this.conversationId = activity.conversation.id;\n }\n\n // Skip own echoed activities\n if (activity.from.id === this.userId) {\n // Echoed user message → mark the original as \"read\"\n if (activity.type === \"message\") {\n const pendingId = this.pendingIds.shift();\n if (pendingId) {\n this.messageStatusHandler?.(pendingId, \"read\");\n }\n }\n return;\n }\n\n // Bot-initiated event\n if (activity.type === \"event\" && activity.name) {\n // Built-in: DisableFeedbackButton — mark the message as feedback-sent\n if (\n activity.name === \"DisableFeedbackButton\" &&\n activity.value\n ) {\n const val = activity.value as {\n CorrelationId?: string;\n FeedbackType?: number;\n };\n if (val.CorrelationId) {\n this.handleDisableFeedback(\n val.CorrelationId,\n val.FeedbackType,\n );\n }\n }\n\n // Dispatch to custom event handler (if registered)\n const handler = this.options.eventHandlers?.[activity.name];\n if (handler) {\n handler(this.createEventContext(activity));\n }\n return;\n }\n\n const result = mapActivityToMessage(activity, this.userId);\n\n if (result === TYPING_SENTINEL) {\n this.handleTyping();\n return;\n }\n\n if (result !== null) {\n // Clear typing indicator when a message arrives\n this.clearTypingTimeout();\n this.typingHandler?.(false);\n\n // First bot message → resolve connect() and signal \"connected\"\n if (this.resolveReady) {\n this.resolveReady();\n this.resolveReady = null;\n }\n\n this.messageHandler?.(result);\n\n // Persist state after delivering a message\n if (this.options.resumeConversation) {\n this.persistConversation();\n }\n }\n } catch (err) {\n console.warn(\n \"[DirectLineConnector] Activity mapping error:\",\n err,\n );\n }\n });\n }\n\n /** Build the context object passed to custom event handlers. */\n private createEventContext(activity: Activity): EventHandlerContext {\n const from = { id: this.userId, name: this.userName ?? this.userId };\n return {\n activity,\n userId: this.userId,\n userName: this.userName ?? this.userId,\n postEvent: (name: string, value?: unknown) => {\n this.directLine\n .postActivity({\n type: \"event\",\n name,\n from,\n ...(this.options.locale\n ? { locale: this.options.locale }\n : {}),\n value,\n })\n .subscribe();\n },\n chativa: this.chativaCtx!,\n };\n }\n\n /** Send webchat/join (first connect) or webchat/rejoin (reconnect) event. */\n private sendJoinEvent() {\n const locale = this.options.locale;\n const from = { id: this.userId, name: this.userName ?? this.userId };\n // Read reserved for future join-vs-rejoin branching; keeps the field alive.\n void this.hasConnectedBefore;\n\n // Skip join/rejoin when resuming a persisted conversation\n if (this._skipNextJoin) {\n this._skipNextJoin = false;\n this.hasConnectedBefore = true;\n this.directLine\n .postActivity({\n type: \"event\",\n name: \"webchat/rejoin\",\n from,\n ...(locale ? { locale } : {}),\n value: { ...(locale ? { language: locale } : {}) },\n })\n .subscribe();\n return;\n }\n this.directLine\n .postActivity({\n type: \"event\",\n name: \"webchat/join\",\n from,\n ...(locale ? { locale } : {}),\n value: {\n ...(locale ? { language: locale } : {}),\n ...this.options.joinParameters,\n },\n })\n .subscribe();\n }\n\n /** Handle DisableFeedbackButton event — find the message by correlationId and patch it. */\n private handleDisableFeedback(\n correlationId: string,\n feedbackType?: number,\n ) {\n const messages = this.chativaCtx?.messages.getAll();\n if (!messages) return;\n const msg = messages.find(\n (m) =>\n (m.data?.channelData as Record<string, unknown> | undefined)\n ?.correlationId === correlationId,\n );\n if (msg) {\n this.chativaCtx!.messages.update(msg.id, {\n data: { ...msg.data, feedbackDisabled: true, feedbackType },\n });\n }\n }\n\n private handleTyping() {\n this.clearTypingTimeout();\n this.typingHandler?.(true);\n if (this.options.typingUntilMessage) {\n // No timer — rely on next bot message (handled by ChatEngine) to clear.\n return;\n }\n const ms = this.options.typingTimeoutMs ?? 3000;\n this.typingTimeout = setTimeout(() => {\n this.typingHandler?.(false);\n this.typingTimeout = null;\n }, ms);\n }\n\n private clearTypingTimeout() {\n if (this.typingTimeout !== null) {\n clearTimeout(this.typingTimeout);\n this.typingTimeout = null;\n }\n }\n\n /* ── Token refresh ──────────────────────────────────────────────── */\n\n /** Schedule a token refresh 60 seconds before expiry. */\n private scheduleTokenRefresh() {\n this.clearRefreshTimer();\n const expiry = getTokenExpiry(this.token);\n if (!expiry) return;\n\n const delay = expiry - Date.now() - 60_000;\n if (delay <= 0) {\n // Token is already about to expire — refresh immediately\n this.refreshTokenNow();\n return;\n }\n this.refreshTimer = setTimeout(() => this.refreshTokenNow(), delay);\n }\n\n /** Pre-emptively refresh the token before it expires. */\n private async refreshTokenNow() {\n try {\n const result = await refreshDirectLineToken(\n this.token,\n this.options.domain,\n );\n this.token = result.token;\n this.scheduleTokenRefresh();\n if (this.options.resumeConversation) {\n this.persistConversation();\n }\n } catch (err) {\n console.warn(\"[DirectLineConnector] Token refresh failed:\", err);\n }\n }\n\n /**\n * Called when DirectLine emits ExpiredToken status.\n * Refreshes the token and recreates the DirectLine connection.\n */\n private async handleExpiredToken() {\n try {\n const result = await refreshDirectLineToken(\n this.token,\n this.options.domain,\n );\n this.token = result.token;\n this.scheduleTokenRefresh();\n } catch {\n if (this.options.resumeConversation) {\n this.clearPersistedConversation();\n }\n this.disconnectHandler?.(\"Token expired and refresh failed\");\n return;\n }\n\n // Tear down old DirectLine\n this.activitySub?.unsubscribe();\n this.connectionSub?.unsubscribe();\n this.clearTypingTimeout();\n try {\n this.directLine.end();\n } catch {\n /* already ended */\n }\n\n // Recreate with new token, preserving conversation\n this.directLine = new DirectLine({\n token: this.token,\n domain: this.options.domain,\n conversationId: this.conversationId,\n watermark: this.watermark,\n });\n\n this.startListening(true);\n\n if (this.options.resumeConversation) {\n this.persistConversation();\n }\n }\n\n private clearRefreshTimer() {\n if (this.refreshTimer !== null) {\n clearTimeout(this.refreshTimer);\n this.refreshTimer = null;\n }\n }\n\n /* ── Conversation persistence ───────────────────────────────────── */\n\n private persistConversation() {\n if (!this.conversationId || !this.token) return;\n try {\n const data: PersistedConversation = {\n conversationId: this.conversationId,\n token: this.token,\n watermark: this.watermark,\n userId: this.userId,\n };\n localStorage.setItem(CONVERSATION_KEY, JSON.stringify(data));\n } catch {\n // localStorage unavailable\n }\n }\n\n private loadPersistedConversation(): PersistedConversation | null {\n try {\n const raw = localStorage.getItem(CONVERSATION_KEY);\n if (!raw) return null;\n return JSON.parse(raw) as PersistedConversation;\n } catch {\n return null;\n }\n }\n\n private clearPersistedConversation() {\n try {\n localStorage.removeItem(CONVERSATION_KEY);\n } catch {\n // best-effort\n }\n }\n}\n"],"names":["TYPING_SENTINEL","CT_HERO","CT_THUMBNAIL","CT_ADAPTIVE","CT_SIGNIN","CT_OAUTH","CT_RECEIPT","CT_AUDIO","CT_VIDEO","CT_ANIMATION","CT_FLEX","mapActivityToMessage","activity","userId","msg","id","timestamp","channelData","suggestedActions","mapSuggestedActions","result","mapAttachments","attachments","layout","cardTypes","adaptiveCardToCardData","mapHeroLikeCard","mapSingleAttachment","att","ct","content","mapAdaptiveCard","mapCardButtons","mapReceiptCard","mediaUrl","buttons","btn","label","actions","a","walkAdaptiveElements","elements","texts","onImage","el","mapAdaptiveActions","col","parseAdaptiveCardBody","image","url","fallback","out","lines","fact","item","price","USER_ID_KEY","CONVERSATION_KEY","randomUserId","getOrCreateUserId","stored","getTokenExpiry","token","payload","fetchToken","secret","res","data","fetchTokenFromUrl","refreshDirectLineToken","currentToken","domain","DirectLineConnector","options","ctx","name","handler","isResuming","persisted","refreshed","DirectLine","ready","resolve","message","reject","err","file","formData","rawType","type","messageId","feedback","correlationId","m","feedbackType","cursor","messages","callback","resolveOnOnline","status","ConnectionStatus","pendingId","val","from","value","locale","ms","expiry","delay","raw"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chativa/connector-directline",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "Chativa DirectLine connector — Azure Bot Framework DirectLine v3 adapter.",
5
5
  "author": "Hamza Agar",
6
6
  "license": "MIT",
@@ -48,7 +48,7 @@
48
48
  "vite": "^7.0.3",
49
49
  "vite-plugin-dts": "^4.5.4",
50
50
  "vitest": "^4.0.18",
51
- "@chativa/core": "0.7.2"
51
+ "@chativa/core": "0.7.3"
52
52
  },
53
53
  "scripts": {
54
54
  "build": "vite build && vite build --config vite.config.cdn.ts",