@chativa/connector-directline 0.5.0 → 0.7.0
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/chativa-directline.global.js +1 -1
- package/dist/chativa-directline.global.js.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +22 -1
- package/dist/index.js +56 -27
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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",
|
|
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";
|
|
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 =
|
|
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);
|
|
8
8
|
if (e.attachments && e.attachments.length > 0) {
|
|
9
|
-
const a =
|
|
9
|
+
const a = N(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
|
|
27
|
-
const n = i.attachments, s = i.attachmentLayout, r = [k, b, T,
|
|
26
|
+
function N(i, t, e) {
|
|
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 ===
|
|
33
|
+
cards: n.map((a) => a.contentType === m ? R(
|
|
34
34
|
a.content
|
|
35
35
|
) : I(a.content))
|
|
36
36
|
},
|
|
37
37
|
timestamp: e
|
|
38
|
-
} :
|
|
38
|
+
} : L(n[0], i, t, e);
|
|
39
39
|
}
|
|
40
|
-
function
|
|
40
|
+
function L(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;
|
|
@@ -49,7 +49,7 @@ function N(i, t, e, n) {
|
|
|
49
49
|
timestamp: n
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
|
-
if (s ===
|
|
52
|
+
if (s === m)
|
|
53
53
|
return _(i.content, e, n);
|
|
54
54
|
if (s === S || s === H) {
|
|
55
55
|
const r = i.content;
|
|
@@ -59,7 +59,7 @@ function N(i, t, e, n) {
|
|
|
59
59
|
from: "bot",
|
|
60
60
|
data: {
|
|
61
61
|
text: r.text ?? "Please sign in",
|
|
62
|
-
buttons:
|
|
62
|
+
buttons: w(r.buttons)
|
|
63
63
|
},
|
|
64
64
|
timestamp: n
|
|
65
65
|
};
|
|
@@ -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:
|
|
146
|
+
buttons: w(i.buttons)
|
|
147
147
|
};
|
|
148
148
|
}
|
|
149
|
-
function
|
|
149
|
+
function w(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 C(i) {
|
|
|
160
160
|
}
|
|
161
161
|
});
|
|
162
162
|
}
|
|
163
|
-
function
|
|
163
|
+
function U(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
|
|
195
|
+
function C(i) {
|
|
196
196
|
const t = [];
|
|
197
197
|
let e;
|
|
198
198
|
const n = [];
|
|
@@ -205,8 +205,8 @@ function w(i) {
|
|
|
205
205
|
}
|
|
206
206
|
), Array.isArray(i.actions) && x(i.actions, n), { texts: t, image: e, buttons: n };
|
|
207
207
|
}
|
|
208
|
-
function
|
|
209
|
-
const { texts: t, image: e, buttons: n } =
|
|
208
|
+
function R(i) {
|
|
209
|
+
const { texts: t, image: e, buttons: n } = C(i);
|
|
210
210
|
return {
|
|
211
211
|
image: e,
|
|
212
212
|
title: t[0] ?? "",
|
|
@@ -216,7 +216,7 @@ function U(i) {
|
|
|
216
216
|
};
|
|
217
217
|
}
|
|
218
218
|
function _(i, t, e) {
|
|
219
|
-
const { texts: n, image: s, buttons: r } =
|
|
219
|
+
const { texts: n, image: s, buttons: r } = C(i), o = i.fallbackText ?? i.speak ?? n.join(`
|
|
220
220
|
`);
|
|
221
221
|
return s ? {
|
|
222
222
|
id: t,
|
|
@@ -294,7 +294,7 @@ function B(i) {
|
|
|
294
294
|
return null;
|
|
295
295
|
}
|
|
296
296
|
}
|
|
297
|
-
async function
|
|
297
|
+
async function F(i, t) {
|
|
298
298
|
const e = await fetch(
|
|
299
299
|
"https://directline.botframework.com/v3/directline/tokens/generate",
|
|
300
300
|
{
|
|
@@ -311,7 +311,7 @@ async function j(i, t) {
|
|
|
311
311
|
const n = await e.json();
|
|
312
312
|
return { token: n.token, conversationId: n.conversationId };
|
|
313
313
|
}
|
|
314
|
-
async function
|
|
314
|
+
async function j(i) {
|
|
315
315
|
const t = await fetch(i, { method: "POST" });
|
|
316
316
|
if (!t.ok)
|
|
317
317
|
throw new Error(`Token generator failed: ${t.status}`);
|
|
@@ -379,14 +379,14 @@ class J {
|
|
|
379
379
|
}
|
|
380
380
|
if (!t)
|
|
381
381
|
if (this.options.tokenGeneratorUrl) {
|
|
382
|
-
const n = await
|
|
382
|
+
const n = await j(
|
|
383
383
|
this.options.tokenGeneratorUrl
|
|
384
384
|
);
|
|
385
385
|
this.token = n.token, n.conversationId && (this.conversationId = n.conversationId), n.userId && (this.userId = n.userId);
|
|
386
386
|
} else if (this.options.token)
|
|
387
387
|
this.token = this.options.token;
|
|
388
388
|
else if (this.options.secret) {
|
|
389
|
-
const n = await
|
|
389
|
+
const n = await F(
|
|
390
390
|
this.options.secret,
|
|
391
391
|
this.userId
|
|
392
392
|
);
|
|
@@ -451,6 +451,32 @@ class J {
|
|
|
451
451
|
if (!r.ok)
|
|
452
452
|
throw new Error(`DirectLine file upload failed: ${r.status}`);
|
|
453
453
|
}
|
|
454
|
+
/**
|
|
455
|
+
* Submit an end-of-conversation survey as a DirectLine event activity.
|
|
456
|
+
* Matches the legacy `webchat/customerfeedback` event shape so existing
|
|
457
|
+
* bot flows keep working:
|
|
458
|
+
* value: { rating, comment, type }
|
|
459
|
+
* where `type` is `kind` coerced to a number (defaulting to 1) to preserve
|
|
460
|
+
* compatibility with bots that switch on numeric survey types.
|
|
461
|
+
*/
|
|
462
|
+
async sendSurvey(t) {
|
|
463
|
+
const e = typeof t.kind == "number" ? t.kind : t.kind !== void 0 ? Number(t.kind) : 1, n = Number.isFinite(e) ? e : 1;
|
|
464
|
+
return new Promise((s, r) => {
|
|
465
|
+
this.directLine.postActivity({
|
|
466
|
+
type: "event",
|
|
467
|
+
name: "webchat/customerfeedback",
|
|
468
|
+
from: { id: this.userId, name: this.userId },
|
|
469
|
+
value: {
|
|
470
|
+
rating: t.rating,
|
|
471
|
+
comment: t.comment ?? "",
|
|
472
|
+
type: n
|
|
473
|
+
}
|
|
474
|
+
}).subscribe({
|
|
475
|
+
next: () => s(),
|
|
476
|
+
error: (o) => r(o)
|
|
477
|
+
});
|
|
478
|
+
});
|
|
479
|
+
}
|
|
454
480
|
async sendFeedback(t, e) {
|
|
455
481
|
const s = this.chativaCtx?.messages.getAll().find((o) => o.id === t)?.data?.channelData?.correlationId;
|
|
456
482
|
if (!s) {
|
|
@@ -482,12 +508,12 @@ class J {
|
|
|
482
508
|
const r = await s.json(), o = [];
|
|
483
509
|
for (const a of r.activities) {
|
|
484
510
|
if (a.from.id === this.userId && a.type === "message") {
|
|
485
|
-
const
|
|
486
|
-
|
|
511
|
+
const p = a;
|
|
512
|
+
p.text && o.push({
|
|
487
513
|
id: a.id ?? `dl-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
|
|
488
514
|
type: "text",
|
|
489
515
|
from: "user",
|
|
490
|
-
data: { text:
|
|
516
|
+
data: { text: p.text },
|
|
491
517
|
timestamp: a.timestamp ? new Date(a.timestamp).getTime() : Date.now()
|
|
492
518
|
});
|
|
493
519
|
continue;
|
|
@@ -596,7 +622,7 @@ class J {
|
|
|
596
622
|
/** Send webchat/join (first connect) or webchat/rejoin (reconnect) event. */
|
|
597
623
|
sendJoinEvent() {
|
|
598
624
|
const t = this.options.locale, e = { id: this.userId, name: this.userName ?? this.userId };
|
|
599
|
-
if (this._skipNextJoin) {
|
|
625
|
+
if (this.hasConnectedBefore, this._skipNextJoin) {
|
|
600
626
|
this._skipNextJoin = !1, this.hasConnectedBefore = !0, this.directLine.postActivity({
|
|
601
627
|
type: "event",
|
|
602
628
|
name: "webchat/rejoin",
|
|
@@ -629,9 +655,12 @@ class J {
|
|
|
629
655
|
});
|
|
630
656
|
}
|
|
631
657
|
handleTyping() {
|
|
632
|
-
this.clearTypingTimeout(), this.typingHandler?.(!0), this.
|
|
658
|
+
if (this.clearTypingTimeout(), this.typingHandler?.(!0), this.options.typingUntilMessage)
|
|
659
|
+
return;
|
|
660
|
+
const t = this.options.typingTimeoutMs ?? 3e3;
|
|
661
|
+
this.typingTimeout = setTimeout(() => {
|
|
633
662
|
this.typingHandler?.(!1), this.typingTimeout = null;
|
|
634
|
-
},
|
|
663
|
+
}, t);
|
|
635
664
|
}
|
|
636
665
|
clearTypingTimeout() {
|
|
637
666
|
this.typingTimeout !== null && (clearTimeout(this.typingTimeout), this.typingTimeout = null);
|
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} 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\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 (used for join vs rejoin). */\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 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\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 // Auto-clear typing after 3 seconds (bot may not send a stop signal)\n this.typingTimeout = setTimeout(() => {\n this.typingHandler?.(false);\n this.typingTimeout = null;\n }, 3000);\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","messageId","feedback","correlationId","m","feedbackType","cursor","messages","callback","resolveOnOnline","status","ConnectionStatus","pendingId","val","from","value","locale","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 /** 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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chativa/connector-directline",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
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.
|
|
51
|
+
"@chativa/core": "0.7.0"
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
54
54
|
"build": "vite build && vite build --config vite.config.cdn.ts",
|