@webority/chat-react 0.0.0-stage → 0.22.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.
@@ -0,0 +1,1188 @@
1
+ import { AppActionIcon as e, AppAlert as t, AppButton as n, AppCard as r, AppConfirmDialog as i, AppDataTable as a, AppEmptyState as o, AppIcon as s, AppLink as c, AppSidebarMenu as l, AppSkeleton as u, AppSpinner as d, AppTextarea as f } from "@webority/ui-react";
2
+ import { Fragment as p, useCallback as m, useEffect as h, useId as g, useRef as _, useState as v } from "react";
3
+ import { Fragment as y, jsx as b, jsxs as x } from "react/jsx-runtime";
4
+ //#region src/lib/sse.js
5
+ function S(e) {
6
+ let t = "";
7
+ function n(t) {
8
+ let n = "message", r = [];
9
+ for (let e of t.split("\n")) {
10
+ if (e === "" || e.startsWith(":")) continue;
11
+ let t = e.indexOf(":"), i = t === -1 ? e : e.slice(0, t), a = t === -1 ? "" : e.slice(t + 1);
12
+ a.startsWith(" ") && (a = a.slice(1)), i === "event" ? n = a : i === "data" && r.push(a);
13
+ }
14
+ if (r.length === 0) return;
15
+ let i;
16
+ try {
17
+ i = JSON.parse(r.join("\n"));
18
+ } catch {
19
+ e({
20
+ name: "error",
21
+ data: {
22
+ code: "invalid-response",
23
+ message: null
24
+ }
25
+ });
26
+ return;
27
+ }
28
+ e({
29
+ name: n,
30
+ data: i
31
+ });
32
+ }
33
+ return {
34
+ push(e) {
35
+ if (!e) return;
36
+ t = (t + e).replace(/\r\n/g, "\n").replace(/\r(?!$)/g, "\n");
37
+ let r = t.split("\n\n");
38
+ t = r.pop();
39
+ for (let e of r) n(e);
40
+ },
41
+ end() {
42
+ let e = t.replace(/\r$/, "");
43
+ t = "", e.trim() && n(e);
44
+ }
45
+ };
46
+ }
47
+ //#endregion
48
+ //#region src/client.js
49
+ var C = "Something went wrong. Please try again.", w = class extends Error {
50
+ constructor(e, t, n, r = null) {
51
+ super(t), this.name = "ChatApiError", this.code = e, this.status = n, this.resetsAtUtc = r;
52
+ }
53
+ };
54
+ function T(e) {
55
+ if (typeof e == "string") try {
56
+ return JSON.parse(e);
57
+ } catch {
58
+ return null;
59
+ }
60
+ return e ?? null;
61
+ }
62
+ function E(e, t) {
63
+ return t?.aborted || e?.code === "ERR_CANCELED" || e?.name === "CanceledError" || e?.name === "AbortError";
64
+ }
65
+ function D(e, t) {
66
+ if (e instanceof w) return e;
67
+ if (E(e, t)) return new w("aborted", "The request was cancelled.");
68
+ let n = e?.response;
69
+ if (!n) return new w("network", C);
70
+ let r = T(n.data), i = typeof r?.code == "string" && r.code ? r.code : "unknown", a = typeof r?.message == "string" && r.message ? r.message : C, o = typeof r?.resetsAtUtc == "string" ? r.resetsAtUtc : null;
71
+ return new w(i, a, n.status, o);
72
+ }
73
+ async function O(e) {
74
+ try {
75
+ return (await e()).data;
76
+ } catch (e) {
77
+ throw D(e);
78
+ }
79
+ }
80
+ function k(e) {
81
+ let t = e?.event?.target;
82
+ if (!(!t || typeof t.responseText != "string") && !(typeof t.status == "number" && (t.status < 200 || t.status >= 300))) return t.responseText;
83
+ }
84
+ function A(e, { base: t }) {
85
+ if (typeof t != "string" || t.trim() === "") throw TypeError("createChatClient needs a base path, e.g. { base: \"/api/assistant\" }.");
86
+ let n = t.replace(/\/+$/, ""), r = (e) => `${n}/conversations/${encodeURIComponent(e)}`;
87
+ async function i({ message: t, conversationId: r, pageContext: i }, { signal: a, onEvent: o } = {}) {
88
+ let s = null, c = null, l = S(({ name: e, data: t }) => {
89
+ s || c || (e === "done" ? s = t : e === "error" ? c = t : (e === "delta" || e === "reset" || e === "actions") && o?.(e, t));
90
+ }), u = 0, d = (e) => {
91
+ typeof e != "string" || e.length <= u || (l.push(e.slice(u)), u = e.length);
92
+ }, f = { message: t };
93
+ r && (f.conversationId = r), i != null && (f.pageContext = i);
94
+ let p;
95
+ try {
96
+ p = await e.post(`${n}/chat`, f, {
97
+ responseType: "text",
98
+ headers: { Accept: "text/event-stream" },
99
+ signal: a,
100
+ onDownloadProgress: (e) => d(k(e))
101
+ });
102
+ } catch (e) {
103
+ throw D(e, a);
104
+ }
105
+ if (d(p.data), l.end(), c) throw new w(c.code || "unknown", c.message || C);
106
+ if (!s) throw new w("invalid-response", C, p.status);
107
+ return s;
108
+ }
109
+ return {
110
+ sendMessage: i,
111
+ getAllowance: () => O(() => e.get(`${n}/allowance`)),
112
+ listConversations: ({ skip: t, take: r } = {}) => {
113
+ let i = new URLSearchParams();
114
+ t != null && i.append("skip", String(t)), r != null && i.append("take", String(r));
115
+ let a = i.toString();
116
+ return O(() => e.get(`${n}/conversations${a ? `?${a}` : ""}`));
117
+ },
118
+ getConversation: (t) => O(() => e.get(r(t))),
119
+ deleteConversation: async (t) => {
120
+ await O(() => e.delete(r(t)));
121
+ },
122
+ rateMessage: async (t, n, { rating: i, note: a }) => {
123
+ let o = typeof a == "string" ? a.trim() : "";
124
+ await O(() => e.put(`${r(t)}/messages/${encodeURIComponent(n)}/rating`, {
125
+ rating: i,
126
+ note: o || null
127
+ }));
128
+ }
129
+ };
130
+ }
131
+ //#endregion
132
+ //#region src/labels.js
133
+ var j = Object.freeze({
134
+ launcher: "Ask the assistant",
135
+ panelTitle: "Assistant",
136
+ newChat: "New chat",
137
+ close: "Close",
138
+ thread: "Conversation",
139
+ you: "You",
140
+ assistant: "Assistant",
141
+ thinking: "Thinking",
142
+ emptyTitle: "How can I help?",
143
+ emptyText: "Ask a question about what you see on this page.",
144
+ composer: "Your question",
145
+ placeholder: "Ask a question",
146
+ send: "Send",
147
+ composerHint: "Press Enter to send, Shift and Enter for a new line.",
148
+ allowance: (e) => e === 0 ? "You have no questions left today." : e === 1 ? "You have 1 question left today." : `You have ${e} questions left today.`,
149
+ disclaimer: "Answers are written by AI and can be wrong. Check anything important.",
150
+ loadingConversation: "Loading the conversation",
151
+ rateUp: "Helpful",
152
+ rateDown: "Not helpful",
153
+ rated: "Thanks for the feedback.",
154
+ ratingNote: "What was wrong with this answer?",
155
+ ratingNoteHint: "Optional.",
156
+ ratingNoteSend: "Send",
157
+ ratingNoteSkip: "Skip",
158
+ ratingFailed: "Your rating did not save. Please try again.",
159
+ actionRaiseTicket: "New support ticket",
160
+ actionReply: (e) => `Reply on ${e}`,
161
+ actionReopen: (e) => `Reopen ${e}`,
162
+ actionNote: "Nothing is sent until you confirm.",
163
+ actionConfirm: "Confirm",
164
+ actionDismiss: "Not now",
165
+ actionDismissed: "Not sent.",
166
+ actionExpired: "This request expired and was not sent. Ask again if you still need it.",
167
+ actionFailed: "We could not send this. Please try again.",
168
+ actionDoneRaiseTicket: (e) => `Ticket ${e} raised.`,
169
+ actionDoneReply: (e) => `Your reply was added to ${e}.`,
170
+ actionDoneReopen: (e) => `${e} is open again.`,
171
+ viewTicket: "View ticket",
172
+ conversations: "Past chats",
173
+ conversationsEmptyTitle: "No past chats",
174
+ conversationsEmptyText: "Your conversations with the assistant show here.",
175
+ untitled: "Untitled chat",
176
+ deleteConversation: "Delete chat",
177
+ deleteConfirmTitle: "Delete this chat?",
178
+ deleteConfirmMessage: "The conversation is removed for good.",
179
+ deleteConfirm: "Delete",
180
+ deleteFailed: "We could not delete this chat. Please try again.",
181
+ cancel: "Cancel",
182
+ loadMore: "Show more",
183
+ loadFailed: "We could not load your chats. Please try again.",
184
+ retry: "Try again"
185
+ });
186
+ function M(e) {
187
+ return e ? {
188
+ ...j,
189
+ ...e
190
+ } : j;
191
+ }
192
+ //#endregion
193
+ //#region src/components/ActionCard.jsx
194
+ function N(e, t) {
195
+ return e.kind === "Reply" ? t.actionReply(e.ticketNumber) : e.kind === "Reopen" ? t.actionReopen(e.ticketNumber) : t.actionRaiseTicket;
196
+ }
197
+ function P(e, t, n) {
198
+ return e === "Reply" ? n.actionDoneReply(t) : e === "Reopen" ? n.actionDoneReopen(t) : n.actionDoneRaiseTicket(t);
199
+ }
200
+ function F({ action: e, confirmAction: i, onViewTicket: a, labels: o }) {
201
+ let s = M(o), [c, l] = v("ready"), [u, d] = v(null), [f, p] = v("");
202
+ if (c === "dismissed") return /* @__PURE__ */ b("p", {
203
+ className: "wui-text-sm text-body-secondary mb-0",
204
+ children: s.actionDismissed
205
+ });
206
+ if (c === "done") return /* @__PURE__ */ b(t, {
207
+ variant: "success",
208
+ role: "status",
209
+ size: "sm",
210
+ action: a ? /* @__PURE__ */ b(n, {
211
+ size: "sm",
212
+ variant: "ghost",
213
+ onClick: () => a(u),
214
+ children: s.viewTicket
215
+ }) : void 0,
216
+ children: P(e.kind, u.number, s)
217
+ });
218
+ async function m() {
219
+ l("sending"), p("");
220
+ try {
221
+ d(await i(e.token)), l("done");
222
+ } catch (e) {
223
+ p(e?.message || s.actionFailed), l("ready");
224
+ }
225
+ }
226
+ let h = c === "sending", g = new Date(e.expiresDateTimeUtc).getTime() <= Date.now(), _ = e.kind === "RaiseTicket" ? [e.category, e.subject].filter(Boolean).join(" · ") : "";
227
+ return /* @__PURE__ */ b(r, {
228
+ padding: "sm",
229
+ className: "border",
230
+ title: N(e, s),
231
+ subtitle: _ || void 0,
232
+ children: /* @__PURE__ */ x("div", {
233
+ className: "d-flex flex-column gap-2",
234
+ children: [e.kind !== "Reopen" && e.body && /* @__PURE__ */ b("p", {
235
+ className: "wui-text-sm mb-0",
236
+ style: {
237
+ whiteSpace: "pre-wrap",
238
+ overflowWrap: "anywhere"
239
+ },
240
+ children: e.body
241
+ }), g ? /* @__PURE__ */ b("p", {
242
+ className: "wui-text-sm text-body-secondary mb-0",
243
+ children: s.actionExpired
244
+ }) : /* @__PURE__ */ x(y, { children: [
245
+ /* @__PURE__ */ b("p", {
246
+ className: "wui-text-xs text-body-secondary mb-0",
247
+ children: s.actionNote
248
+ }),
249
+ f && /* @__PURE__ */ b(t, {
250
+ size: "sm",
251
+ variant: "danger",
252
+ children: f
253
+ }),
254
+ /* @__PURE__ */ x("div", {
255
+ className: "d-flex flex-wrap gap-2",
256
+ children: [/* @__PURE__ */ b(n, {
257
+ size: "sm",
258
+ loading: h,
259
+ onClick: m,
260
+ children: s.actionConfirm
261
+ }), /* @__PURE__ */ b(n, {
262
+ size: "sm",
263
+ variant: "secondary",
264
+ disabled: h,
265
+ onClick: () => l("dismissed"),
266
+ children: s.actionDismiss
267
+ })]
268
+ })
269
+ ] })]
270
+ })
271
+ });
272
+ }
273
+ //#endregion
274
+ //#region src/components/ChatComposer.jsx
275
+ function I({ onSubmit: e, busy: t = !1, disabled: r = !1, maxLength: i = 4e3, inputRef: a, labels: o }) {
276
+ let s = M(o), c = g(), [l, u] = v(""), d = t || r || !l.trim();
277
+ function p() {
278
+ d || (e(l.trim()), u(""));
279
+ }
280
+ return /* @__PURE__ */ x("form", {
281
+ className: "d-flex align-items-end gap-2",
282
+ "aria-label": s.composer,
283
+ onSubmit: (e) => {
284
+ e.preventDefault(), p();
285
+ },
286
+ children: [
287
+ /* @__PURE__ */ b(f, {
288
+ id: `${c}-message`,
289
+ "aria-label": s.composer,
290
+ "aria-describedby": `${c}-hint`,
291
+ placeholder: s.placeholder,
292
+ rows: 1,
293
+ autoGrow: !0,
294
+ maxLength: i,
295
+ value: l,
296
+ disabled: r,
297
+ ref: a,
298
+ fieldClassName: "flex-grow-1 mb-0",
299
+ onChange: (e) => u(e.target.value),
300
+ onKeyDown: (e) => {
301
+ e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing && (e.preventDefault(), p());
302
+ }
303
+ }),
304
+ /* @__PURE__ */ b("span", {
305
+ id: `${c}-hint`,
306
+ className: "visually-hidden",
307
+ children: s.composerHint
308
+ }),
309
+ /* @__PURE__ */ b(n, {
310
+ type: "submit",
311
+ leftIcon: "send",
312
+ disabled: d,
313
+ children: /* @__PURE__ */ b("span", {
314
+ className: "visually-hidden",
315
+ children: s.send
316
+ })
317
+ })
318
+ ]
319
+ });
320
+ }
321
+ //#endregion
322
+ //#region src/lib/format.js
323
+ var ee = new Intl.DateTimeFormat("en-IN", {
324
+ day: "2-digit",
325
+ month: "numeric",
326
+ year: "numeric",
327
+ hour: "numeric",
328
+ minute: "2-digit",
329
+ hour12: !0,
330
+ timeZoneName: "short"
331
+ }), te = [
332
+ "Jan",
333
+ "Feb",
334
+ "Mar",
335
+ "Apr",
336
+ "May",
337
+ "Jun",
338
+ "Jul",
339
+ "Aug",
340
+ "Sep",
341
+ "Oct",
342
+ "Nov",
343
+ "Dec"
344
+ ];
345
+ function ne(e) {
346
+ if (!e) return "-";
347
+ let t = new Date(e);
348
+ if (Number.isNaN(t.getTime())) return "-";
349
+ let n = Object.fromEntries(ee.formatToParts(t).map((e) => [e.type, e.value]));
350
+ return `${n.day} ${te[Number(n.month) - 1]} ${n.year}, ${n.hour}:${n.minute} ${n.dayPeriod.toLowerCase()} ${n.timeZoneName}`;
351
+ }
352
+ //#endregion
353
+ //#region src/components/ChatConversationList.jsx
354
+ function re({ client: a, onOpen: s, onDeleted: c, pageSize: l = 20, labels: d }) {
355
+ let f = M(d), [p, g] = v([]), [_, y] = v(!0), [S, C] = v(""), [w, T] = v(!1), [E, D] = v(0), [O, k] = v(null), [A, j] = v(!1), [N, P] = v(""), F = m(async (e) => {
356
+ y(!0), C("");
357
+ try {
358
+ let t = await a.listConversations({
359
+ skip: e,
360
+ take: l
361
+ });
362
+ g((n) => e === 0 ? t : [...n, ...t]), T(t.length === l);
363
+ } catch (e) {
364
+ C(e?.message || f.loadFailed);
365
+ } finally {
366
+ y(!1);
367
+ }
368
+ }, [
369
+ a,
370
+ l,
371
+ f.loadFailed
372
+ ]);
373
+ h(() => {
374
+ F(0);
375
+ }, [F, E]);
376
+ async function I() {
377
+ j(!0), P("");
378
+ try {
379
+ await a.deleteConversation(O.publicId), g((e) => e.filter((e) => e.publicId !== O.publicId)), c?.(O.publicId), k(null);
380
+ } catch (e) {
381
+ P(e?.message || f.deleteFailed);
382
+ } finally {
383
+ j(!1);
384
+ }
385
+ }
386
+ return !_ && !S && p.length === 0 ? /* @__PURE__ */ b(o, {
387
+ icon: "chat",
388
+ size: "sm",
389
+ title: f.conversationsEmptyTitle,
390
+ text: f.conversationsEmptyText
391
+ }) : /* @__PURE__ */ x("div", {
392
+ className: "d-flex flex-column gap-3",
393
+ children: [
394
+ S && /* @__PURE__ */ b(t, {
395
+ variant: "danger",
396
+ action: /* @__PURE__ */ b(n, {
397
+ size: "sm",
398
+ variant: "secondary",
399
+ onClick: () => D((e) => e + 1),
400
+ children: f.retry
401
+ }),
402
+ children: S
403
+ }),
404
+ p.length > 0 && /* @__PURE__ */ b("ul", {
405
+ className: "list-unstyled d-flex flex-column gap-2 mb-0",
406
+ "aria-label": f.conversations,
407
+ children: p.map((t) => /* @__PURE__ */ b("li", { children: /* @__PURE__ */ x(r, {
408
+ padding: "sm",
409
+ className: "border",
410
+ bodyClassName: "d-flex align-items-center gap-2",
411
+ children: [/* @__PURE__ */ b(n, {
412
+ variant: "ghost",
413
+ className: "flex-grow-1 text-start",
414
+ style: { minWidth: 0 },
415
+ onClick: () => s(t),
416
+ children: /* @__PURE__ */ x("span", {
417
+ className: "d-flex flex-column",
418
+ style: { minWidth: 0 },
419
+ children: [/* @__PURE__ */ b("span", {
420
+ className: "text-truncate fw-semibold",
421
+ children: t.title || f.untitled
422
+ }), /* @__PURE__ */ b("time", {
423
+ dateTime: t.lastMessageDateTimeUtc,
424
+ className: "wui-text-xs text-body-secondary",
425
+ children: ne(t.lastMessageDateTimeUtc)
426
+ })]
427
+ })
428
+ }), /* @__PURE__ */ b(e, {
429
+ icon: "trash-2",
430
+ danger: !0,
431
+ label: f.deleteConversation,
432
+ onClick: () => {
433
+ P(""), k(t);
434
+ }
435
+ })]
436
+ }) }, t.publicId))
437
+ }),
438
+ _ && /* @__PURE__ */ x("div", {
439
+ className: "d-flex flex-column gap-2",
440
+ "aria-hidden": "true",
441
+ children: [
442
+ /* @__PURE__ */ b(u, { height: 44 }),
443
+ /* @__PURE__ */ b(u, { height: 44 }),
444
+ /* @__PURE__ */ b(u, { height: 44 })
445
+ ]
446
+ }),
447
+ !_ && w && /* @__PURE__ */ b(n, {
448
+ variant: "secondary",
449
+ className: "align-self-center",
450
+ onClick: () => F(p.length),
451
+ children: f.loadMore
452
+ }),
453
+ /* @__PURE__ */ b(i, {
454
+ open: O !== null,
455
+ title: f.deleteConfirmTitle,
456
+ message: N ? /* @__PURE__ */ b(t, {
457
+ variant: "danger",
458
+ children: N
459
+ }) : f.deleteConfirmMessage,
460
+ confirmLabel: f.deleteConfirm,
461
+ cancelLabel: f.cancel,
462
+ danger: !0,
463
+ loading: A,
464
+ onConfirm: I,
465
+ onClose: () => {
466
+ A || k(null);
467
+ }
468
+ })
469
+ ]
470
+ });
471
+ }
472
+ //#endregion
473
+ //#region src/components/ChatLauncher.jsx
474
+ var ie = { zIndex: "var(--wui-z-fixed)" }, ae = {
475
+ end: "end-0",
476
+ start: "start-0"
477
+ };
478
+ function oe({ onClick: e, open: t = !1, position: r = "end", icon: i = "sparkles", className: a, style: o, labels: s }) {
479
+ let c = M(s);
480
+ return /* @__PURE__ */ b("span", {
481
+ "data-support-capture": "exclude",
482
+ className: [
483
+ "position-fixed bottom-0 m-3",
484
+ ae[r],
485
+ a
486
+ ].filter(Boolean).join(" "),
487
+ style: {
488
+ ...ie,
489
+ ...o
490
+ },
491
+ children: /* @__PURE__ */ b(n, {
492
+ leftIcon: i,
493
+ className: "rounded-pill",
494
+ onClick: e,
495
+ "aria-haspopup": "dialog",
496
+ "aria-expanded": t,
497
+ children: c.launcher
498
+ })
499
+ });
500
+ }
501
+ //#endregion
502
+ //#region src/markdown.jsx
503
+ var se = /^[a-z][a-z0-9+.-]*:[a-z0-9_-]+\/[a-z0-9_.~-]+$/i, L = /^\s*```/, R = /^\s*[-*+]\s+(.*)$/, z = /^\s*(\d{1,9})[.)]\s+(.*)$/, B = /^\s{0,3}#{1,6}\s+(.*?)\s*#*\s*$/, V = /^\s*([-*_])(\s*\1){2,}\s*$/, ce = /^\s*\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)*\|?\s*$/, H = (e) => e.includes("|");
504
+ function U(e) {
505
+ let t = e.trim();
506
+ return t.startsWith("|") && (t = t.slice(1)), t.endsWith("|") && (t = t.slice(0, -1)), t.split("|").map((e) => e.trim());
507
+ }
508
+ function W(e, t) {
509
+ return H(e[t]) && t + 1 < e.length && ce.test(e[t + 1]);
510
+ }
511
+ function G(e, t) {
512
+ let n = e[t];
513
+ return L.test(n) || R.test(n) || z.test(n) || B.test(n) || V.test(n) || W(e, t);
514
+ }
515
+ function le(e) {
516
+ let t = String(e ?? "").replace(/\r\n?/g, "\n").split("\n"), n = [], r = 0;
517
+ for (; r < t.length;) {
518
+ let e = t[r];
519
+ if (!e.trim()) {
520
+ r += 1;
521
+ continue;
522
+ }
523
+ if (L.test(e)) {
524
+ let e = [];
525
+ for (r += 1; r < t.length && !L.test(t[r]);) e.push(t[r]), r += 1;
526
+ r += 1, n.push({
527
+ type: "code",
528
+ text: e.join("\n")
529
+ });
530
+ continue;
531
+ }
532
+ if (W(t, r)) {
533
+ let i = U(e), a = [];
534
+ for (r += 2; r < t.length && t[r].trim() && H(t[r]);) a.push(U(t[r])), r += 1;
535
+ n.push({
536
+ type: "table",
537
+ header: i,
538
+ rows: a
539
+ });
540
+ continue;
541
+ }
542
+ if (V.test(e)) {
543
+ n.push({ type: "rule" }), r += 1;
544
+ continue;
545
+ }
546
+ let i = B.exec(e);
547
+ if (i) {
548
+ n.push({
549
+ type: "heading",
550
+ text: i[1]
551
+ }), r += 1;
552
+ continue;
553
+ }
554
+ let a = z.exec(e);
555
+ if (a || R.test(e)) {
556
+ let e = !!a, i = e ? z : R, o = [];
557
+ for (; r < t.length && t[r].trim();) {
558
+ let n = i.exec(t[r]);
559
+ if (n) o.push(e ? n[2] : n[1]);
560
+ else if (G(t, r)) break;
561
+ else o[o.length - 1] += ` ${t[r].trim()}`;
562
+ r += 1;
563
+ }
564
+ n.push({
565
+ type: "list",
566
+ ordered: e,
567
+ start: e ? Number(a[1]) : 1,
568
+ items: o
569
+ });
570
+ continue;
571
+ }
572
+ let o = [e];
573
+ for (r += 1; r < t.length && t[r].trim() && !G(t, r);) o.push(t[r]), r += 1;
574
+ n.push({
575
+ type: "paragraph",
576
+ lines: o
577
+ });
578
+ }
579
+ return n.map((e, t) => ({
580
+ ...e,
581
+ key: t
582
+ }));
583
+ }
584
+ var K = (e) => !!e && /[\p{L}\p{N}]/u.test(e);
585
+ function q(e, t, n) {
586
+ let r = e.indexOf(n, t);
587
+ for (; r !== -1;) {
588
+ let i = e.slice(t, r), a = n.length === 1 && (e[r + 1] === n || e[r - 1] === n), o = n[0] === "_" && K(e[r + n.length]);
589
+ if (i.trim() && !/^\s/.test(i) && !/\s$/.test(i) && !a && !o) return r;
590
+ r = e.indexOf(n, r + 1);
591
+ }
592
+ return -1;
593
+ }
594
+ function J(e) {
595
+ let t = [], n = "", r = () => {
596
+ n && t.push({
597
+ type: "text",
598
+ text: n
599
+ }), n = "";
600
+ }, i = 0;
601
+ for (; i < e.length;) {
602
+ let a = e[i];
603
+ if (a === "`") {
604
+ let n = e.indexOf("`", i + 1);
605
+ if (n > i + 1) {
606
+ r(), t.push({
607
+ type: "code",
608
+ text: e.slice(i + 1, n)
609
+ }), i = n + 1;
610
+ continue;
611
+ }
612
+ }
613
+ if ((a === "*" || a === "_") && e[i + 1] === a) {
614
+ let o = a + a, s = q(e, i + 2, o);
615
+ if (s !== -1 && !(a === "_" && K(e[i - 1]))) {
616
+ r(), t.push({
617
+ type: "strong",
618
+ children: J(e.slice(i + 2, s))
619
+ }), i = s + 2;
620
+ continue;
621
+ }
622
+ n += o, i += 2;
623
+ continue;
624
+ }
625
+ if (a === "*" || a === "_") {
626
+ let n = q(e, i + 1, a);
627
+ if (n !== -1 && !(a === "_" && K(e[i - 1]))) {
628
+ r(), t.push({
629
+ type: "em",
630
+ children: J(e.slice(i + 1, n))
631
+ }), i = n + 1;
632
+ continue;
633
+ }
634
+ }
635
+ if (a === "[") {
636
+ let n = /^\[([^\]\n]+)\]\(([^)\s]+)\)/.exec(e.slice(i));
637
+ if (n) {
638
+ r(), t.push({
639
+ type: "link",
640
+ href: n[2],
641
+ children: J(n[1])
642
+ }), i += n[0].length;
643
+ continue;
644
+ }
645
+ }
646
+ n += a, i += 1;
647
+ }
648
+ return r(), t.map((e, t) => ({
649
+ ...e,
650
+ key: t
651
+ }));
652
+ }
653
+ function ue(e, t) {
654
+ if (!t || !se.test(e)) return null;
655
+ let n = t(e);
656
+ return typeof n == "string" && n.startsWith("/") && !n.startsWith("//") ? n : null;
657
+ }
658
+ function Y({ tokens: e, resolveLink: t, linkComponent: n }) {
659
+ return e.map((e) => {
660
+ switch (e.type) {
661
+ case "code": return /* @__PURE__ */ b("code", { children: e.text }, e.key);
662
+ case "strong": return /* @__PURE__ */ b("strong", { children: /* @__PURE__ */ b(Y, {
663
+ tokens: e.children,
664
+ resolveLink: t,
665
+ linkComponent: n
666
+ }) }, e.key);
667
+ case "em": return /* @__PURE__ */ b("em", { children: /* @__PURE__ */ b(Y, {
668
+ tokens: e.children,
669
+ resolveLink: t,
670
+ linkComponent: n
671
+ }) }, e.key);
672
+ case "link": {
673
+ let r = /* @__PURE__ */ b(Y, {
674
+ tokens: e.children,
675
+ resolveLink: t,
676
+ linkComponent: n
677
+ }), i = ue(e.href, t);
678
+ return i ? /* @__PURE__ */ b(c, {
679
+ href: i,
680
+ linkComponent: n,
681
+ animation: "static",
682
+ children: r
683
+ }, e.key) : /* @__PURE__ */ b("span", { children: r }, e.key);
684
+ }
685
+ default: return /* @__PURE__ */ b(p, { children: e.text }, e.key);
686
+ }
687
+ });
688
+ }
689
+ function de({ text: e, resolveLink: t, linkComponent: n }) {
690
+ return /* @__PURE__ */ b(Y, {
691
+ tokens: J(e),
692
+ resolveLink: t,
693
+ linkComponent: n
694
+ });
695
+ }
696
+ function fe({ block: e, resolveLink: t, linkComponent: n }) {
697
+ let r = (e) => /* @__PURE__ */ b(de, {
698
+ text: e,
699
+ resolveLink: t,
700
+ linkComponent: n
701
+ });
702
+ switch (e.type) {
703
+ case "heading": return /* @__PURE__ */ b("p", {
704
+ className: "fw-semibold mb-2",
705
+ children: r(e.text)
706
+ });
707
+ case "rule": return /* @__PURE__ */ b("hr", { className: "my-2" });
708
+ case "code": return /* @__PURE__ */ b("pre", {
709
+ className: "wui-text-sm mb-2",
710
+ children: /* @__PURE__ */ b("code", { children: e.text })
711
+ });
712
+ case "list": {
713
+ let t = e.items.map((e, t) => /* @__PURE__ */ b("li", { children: r(e) }, t));
714
+ return e.ordered ? /* @__PURE__ */ b("ol", {
715
+ className: "mb-2 ps-4",
716
+ start: e.start === 1 ? void 0 : e.start,
717
+ children: t
718
+ }) : /* @__PURE__ */ b("ul", {
719
+ className: "mb-2 ps-4",
720
+ children: t
721
+ });
722
+ }
723
+ case "table": return /* @__PURE__ */ b(a, {
724
+ columns: e.header.map((e, t) => ({
725
+ key: `c${t}`,
726
+ label: r(e),
727
+ render: (e) => r(e.cells[t] ?? "")
728
+ })),
729
+ rows: e.rows.map((e, t) => ({
730
+ id: t,
731
+ cells: e
732
+ })),
733
+ density: "compact",
734
+ empty: null,
735
+ wrapperClassName: "mb-2"
736
+ });
737
+ default: return /* @__PURE__ */ b("p", {
738
+ className: "mb-2",
739
+ children: e.lines.map((e, t) => /* @__PURE__ */ x("span", { children: [t > 0 && /* @__PURE__ */ b("br", {}), r(e)] }, t))
740
+ });
741
+ }
742
+ }
743
+ function X({ text: e, resolveLink: t, linkComponent: n, className: r }) {
744
+ let i = le(e);
745
+ return /* @__PURE__ */ b("div", {
746
+ className: ["wui-text-sm text-break", r].filter(Boolean).join(" "),
747
+ children: i.map((e) => /* @__PURE__ */ b(fe, {
748
+ block: e,
749
+ resolveLink: t,
750
+ linkComponent: n
751
+ }, e.key))
752
+ });
753
+ }
754
+ //#endregion
755
+ //#region src/components/ReplyRating.jsx
756
+ function Z({ rating: e = null, onRate: r, noteMaxLength: i = 1e3, labels: a }) {
757
+ let o = M(a), s = g(), [c, l] = v(!1), [u, d] = v(!1), [p, m] = v(""), [h, _] = v(""), [y, S] = v(!1);
758
+ async function C(e, t) {
759
+ l(!0), _("");
760
+ try {
761
+ await r(e, t), d(e === "Down" && t === void 0), S(e === "Up" || t !== void 0), t !== void 0 && m("");
762
+ } catch {
763
+ _(o.ratingFailed);
764
+ } finally {
765
+ l(!1);
766
+ }
767
+ }
768
+ return /* @__PURE__ */ x("div", {
769
+ className: "d-flex flex-column gap-2",
770
+ children: [
771
+ /* @__PURE__ */ x("div", {
772
+ className: "d-flex flex-wrap align-items-center gap-1",
773
+ children: [
774
+ /* @__PURE__ */ b(n, {
775
+ size: "sm",
776
+ variant: e === "Up" ? "subtle" : "ghost",
777
+ leftIcon: "check",
778
+ "aria-pressed": e === "Up",
779
+ disabled: c,
780
+ onClick: () => C("Up"),
781
+ children: o.rateUp
782
+ }),
783
+ /* @__PURE__ */ b(n, {
784
+ size: "sm",
785
+ variant: e === "Down" ? "subtle" : "ghost",
786
+ leftIcon: "x",
787
+ "aria-pressed": e === "Down",
788
+ disabled: c,
789
+ onClick: () => C("Down"),
790
+ children: o.rateDown
791
+ }),
792
+ y && !u && /* @__PURE__ */ b("span", {
793
+ className: "wui-text-xs text-body-secondary",
794
+ role: "status",
795
+ children: o.rated
796
+ })
797
+ ]
798
+ }),
799
+ h && /* @__PURE__ */ b(t, {
800
+ size: "sm",
801
+ variant: "danger",
802
+ children: h
803
+ }),
804
+ u && /* @__PURE__ */ x("form", {
805
+ className: "d-flex flex-column gap-2",
806
+ onSubmit: (e) => {
807
+ e.preventDefault(), C("Down", p);
808
+ },
809
+ children: [/* @__PURE__ */ b(f, {
810
+ id: `${s}-note`,
811
+ label: o.ratingNote,
812
+ hint: o.ratingNoteHint,
813
+ rows: 2,
814
+ maxLength: i,
815
+ value: p,
816
+ onChange: (e) => m(e.target.value)
817
+ }), /* @__PURE__ */ x("div", {
818
+ className: "d-flex gap-2",
819
+ children: [/* @__PURE__ */ b(n, {
820
+ type: "submit",
821
+ size: "sm",
822
+ loading: c,
823
+ children: o.ratingNoteSend
824
+ }), /* @__PURE__ */ b(n, {
825
+ size: "sm",
826
+ variant: "secondary",
827
+ disabled: c,
828
+ onClick: () => {
829
+ d(!1), S(!0);
830
+ },
831
+ children: o.ratingNoteSkip
832
+ })]
833
+ })]
834
+ })
835
+ ]
836
+ });
837
+ }
838
+ //#endregion
839
+ //#region src/components/ChatMessage.jsx
840
+ var pe = {
841
+ maxWidth: "85%",
842
+ whiteSpace: "pre-wrap",
843
+ overflowWrap: "anywhere"
844
+ };
845
+ function Q({ turn: e, onRate: n, resolveLink: i, linkComponent: a, confirmAction: o, onViewTicket: s, labels: c }) {
846
+ let l = M(c), u = e.streaming && !e.answer;
847
+ return /* @__PURE__ */ x("li", {
848
+ className: "d-flex flex-column gap-2",
849
+ children: [e.question && /* @__PURE__ */ x("div", {
850
+ className: "align-self-end",
851
+ style: pe,
852
+ children: [/* @__PURE__ */ x("span", {
853
+ className: "visually-hidden",
854
+ children: [l.you, ": "]
855
+ }), /* @__PURE__ */ b(r, {
856
+ padding: "sm",
857
+ variant: "muted",
858
+ className: "wui-text-sm",
859
+ children: e.question
860
+ })]
861
+ }), /* @__PURE__ */ x("div", {
862
+ className: "d-flex flex-column gap-2",
863
+ style: { minWidth: 0 },
864
+ children: [
865
+ /* @__PURE__ */ x("span", {
866
+ className: "visually-hidden",
867
+ children: [l.assistant, ": "]
868
+ }),
869
+ /* @__PURE__ */ b("div", {
870
+ "aria-live": "polite",
871
+ "aria-busy": e.streaming,
872
+ children: u ? /* @__PURE__ */ x("span", {
873
+ className: "d-inline-flex align-items-center gap-2 wui-text-sm text-body-secondary",
874
+ children: [/* @__PURE__ */ b(d, {
875
+ size: "sm",
876
+ label: l.thinking
877
+ }), /* @__PURE__ */ b("span", {
878
+ "aria-hidden": "true",
879
+ children: l.thinking
880
+ })]
881
+ }) : e.answer && /* @__PURE__ */ b(X, {
882
+ text: e.answer,
883
+ resolveLink: i,
884
+ linkComponent: a
885
+ })
886
+ }),
887
+ e.error && /* @__PURE__ */ b(t, {
888
+ size: "sm",
889
+ variant: "danger",
890
+ children: e.error.message
891
+ }),
892
+ o && !e.streaming && e.actions.map((e) => /* @__PURE__ */ b(F, {
893
+ action: e,
894
+ confirmAction: o,
895
+ onViewTicket: s,
896
+ labels: c
897
+ }, e.token)),
898
+ n && e.messageId && !e.streaming && /* @__PURE__ */ b(Z, {
899
+ rating: e.rating,
900
+ onRate: (t, r) => n(e.id, t, r),
901
+ labels: c
902
+ })
903
+ ]
904
+ })]
905
+ });
906
+ }
907
+ //#endregion
908
+ //#region src/components/ChatThread.jsx
909
+ function $({ turns: e, empty: t, onRate: n, resolveLink: r, linkComponent: i, confirmAction: a, onViewTicket: s, labels: c }) {
910
+ let l = M(c), u = _(null), d = e[e.length - 1];
911
+ return h(() => {
912
+ u.current?.scrollIntoView({ block: "end" });
913
+ }, [
914
+ e.length,
915
+ d?.answer,
916
+ d?.error,
917
+ d?.actions
918
+ ]), e.length === 0 ? t ?? /* @__PURE__ */ b(o, {
919
+ icon: "sparkles",
920
+ size: "sm",
921
+ title: l.emptyTitle,
922
+ text: l.emptyText
923
+ }) : /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b("ol", {
924
+ className: "list-unstyled d-flex flex-column gap-3 mb-0",
925
+ "aria-label": l.thread,
926
+ children: e.map((e) => /* @__PURE__ */ b(Q, {
927
+ turn: e,
928
+ onRate: n,
929
+ resolveLink: r,
930
+ linkComponent: i,
931
+ confirmAction: a,
932
+ onViewTicket: s,
933
+ labels: c
934
+ }, e.id))
935
+ }), /* @__PURE__ */ b("div", { ref: u })] });
936
+ }
937
+ //#endregion
938
+ //#region src/components/ChatPanel.jsx
939
+ function me({ chat: n, open: r, onClose: i, title: a, titleIcon: o = "sparkles", headerActions: c, empty: u, disclaimer: f, maxLength: p = 4e3, allowanceThreshold: m = 10, width: g = "440px", resolveLink: v, linkComponent: y, confirmAction: S, onViewTicket: C, rating: w = !0, labels: T }) {
940
+ let E = M(T), D = _(null), { refreshAllowance: O } = n;
941
+ h(() => {
942
+ r && O().catch(() => {});
943
+ }, [r, O]);
944
+ let k = n.messagesLeftToday, A = a ?? E.panelTitle;
945
+ return /* @__PURE__ */ b(l, {
946
+ show: r,
947
+ onHide: i,
948
+ side: "right",
949
+ width: g,
950
+ header: /* @__PURE__ */ x("div", {
951
+ className: "drawer-header",
952
+ children: [/* @__PURE__ */ x("div", {
953
+ className: "drawer-title",
954
+ children: [o && /* @__PURE__ */ b("span", {
955
+ className: "drawer-title-ic",
956
+ children: /* @__PURE__ */ b(s, {
957
+ name: o,
958
+ size: 18
959
+ })
960
+ }), A]
961
+ }), /* @__PURE__ */ x("div", {
962
+ className: "d-flex align-items-center gap-1",
963
+ children: [
964
+ c,
965
+ /* @__PURE__ */ b(e, {
966
+ icon: "plus",
967
+ label: E.newChat,
968
+ onClick: n.newConversation,
969
+ disabled: n.turns.length === 0 && !n.loading
970
+ }),
971
+ /* @__PURE__ */ b(e, {
972
+ icon: "x",
973
+ label: E.close,
974
+ onClick: i
975
+ })
976
+ ]
977
+ })]
978
+ }),
979
+ footer: /* @__PURE__ */ x("div", {
980
+ className: "d-flex flex-column gap-2",
981
+ children: [
982
+ k !== null && k <= m && /* @__PURE__ */ b("p", {
983
+ className: "wui-text-xs text-body-secondary mb-0",
984
+ role: "status",
985
+ children: E.allowance(k)
986
+ }),
987
+ /* @__PURE__ */ b(I, {
988
+ onSubmit: n.submit,
989
+ busy: n.streaming || n.loading,
990
+ disabled: k === 0,
991
+ maxLength: p,
992
+ inputRef: D,
993
+ labels: T
994
+ }),
995
+ /* @__PURE__ */ b("p", {
996
+ className: "wui-text-xs text-body-secondary mb-0",
997
+ children: f ?? E.disclaimer
998
+ })
999
+ ]
1000
+ }),
1001
+ ariaLabel: typeof A == "string" ? A : E.panelTitle,
1002
+ onEntered: () => D.current?.focus(),
1003
+ children: n.loading ? /* @__PURE__ */ b("div", {
1004
+ className: "d-flex justify-content-center py-4",
1005
+ children: /* @__PURE__ */ b(d, { label: E.loadingConversation })
1006
+ }) : n.loadError ? /* @__PURE__ */ b(t, {
1007
+ variant: "danger",
1008
+ children: n.loadError.message
1009
+ }) : /* @__PURE__ */ b($, {
1010
+ turns: n.turns,
1011
+ empty: u,
1012
+ onRate: w ? n.rate : void 0,
1013
+ resolveLink: v,
1014
+ linkComponent: y,
1015
+ confirmAction: S,
1016
+ onViewTicket: C,
1017
+ labels: T
1018
+ })
1019
+ });
1020
+ }
1021
+ //#endregion
1022
+ //#region src/useChat.js
1023
+ function he(e) {
1024
+ return {
1025
+ code: e?.code || "unknown",
1026
+ message: e?.message || "Something went wrong. Please try again.",
1027
+ resetsAtUtc: e?.resetsAtUtc ?? null
1028
+ };
1029
+ }
1030
+ function ge(e) {
1031
+ if (!e) return [];
1032
+ let t = JSON.parse(e);
1033
+ return Array.isArray(t) ? t : [];
1034
+ }
1035
+ function _e(e) {
1036
+ let t = [];
1037
+ for (let n of e ?? []) {
1038
+ if (n.role === "User") {
1039
+ t.push({
1040
+ id: n.publicId,
1041
+ question: n.content,
1042
+ answer: "",
1043
+ streaming: !1,
1044
+ error: null,
1045
+ actions: [],
1046
+ messageId: null,
1047
+ rating: null,
1048
+ ratingNote: null
1049
+ });
1050
+ continue;
1051
+ }
1052
+ let e = t[t.length - 1], r = {
1053
+ answer: n.content,
1054
+ actions: ge(n.actionsJson),
1055
+ messageId: n.publicId,
1056
+ rating: n.rating ?? null,
1057
+ ratingNote: n.ratingNote ?? null
1058
+ };
1059
+ e && e.messageId === null && e.answer === "" ? Object.assign(e, r) : t.push({
1060
+ id: n.publicId,
1061
+ question: "",
1062
+ streaming: !1,
1063
+ error: null,
1064
+ ...r
1065
+ });
1066
+ }
1067
+ return t;
1068
+ }
1069
+ function ve({ client: e, pageContext: t }) {
1070
+ let [n, r] = v([]), [i, a] = v(null), [o, s] = v(null), [c, l] = v(!1), [u, d] = v(null), f = _(null), p = _(0), g = _(0), y = _(t);
1071
+ y.current = t;
1072
+ let b = _(null);
1073
+ b.current = i;
1074
+ let x = _(n);
1075
+ x.current = n;
1076
+ let S = m(() => {
1077
+ p.current += 1, f.current?.abort(), f.current = null;
1078
+ }, []);
1079
+ h(() => S, [S]);
1080
+ let C = m((e, t) => {
1081
+ r((n) => n.map((n) => n.id === e ? {
1082
+ ...n,
1083
+ ...typeof t == "function" ? t(n) : t
1084
+ } : n));
1085
+ }, []), w = m(async (t) => {
1086
+ let n = typeof t == "string" ? t.trim() : "";
1087
+ if (!n || f.current) return;
1088
+ let i = p.current, o = new AbortController();
1089
+ f.current = o, g.current += 1;
1090
+ let c = `turn-${g.current}`;
1091
+ r((e) => [...e, {
1092
+ id: c,
1093
+ question: n,
1094
+ answer: "",
1095
+ streaming: !0,
1096
+ error: null,
1097
+ actions: [],
1098
+ messageId: null,
1099
+ rating: null,
1100
+ ratingNote: null
1101
+ }]);
1102
+ let l = () => i === p.current && !o.signal.aborted;
1103
+ try {
1104
+ let t = await e.sendMessage({
1105
+ message: n,
1106
+ conversationId: b.current,
1107
+ pageContext: y.current
1108
+ }, {
1109
+ signal: o.signal,
1110
+ onEvent: (e, t) => {
1111
+ l() && (e === "delta" ? C(c, (e) => ({ answer: e.answer + (t?.text ?? "") })) : e === "reset" ? C(c, { answer: "" }) : e === "actions" && C(c, { actions: Array.isArray(t?.actions) ? t.actions : [] }));
1112
+ }
1113
+ });
1114
+ if (!l()) return;
1115
+ C(c, {
1116
+ answer: t.reply,
1117
+ messageId: t.messageId ?? null,
1118
+ streaming: !1
1119
+ }), b.current = t.conversationId, a(t.conversationId), s(t.messagesLeftToday ?? null);
1120
+ } catch (e) {
1121
+ if (!l()) return;
1122
+ C(c, {
1123
+ answer: "",
1124
+ actions: [],
1125
+ streaming: !1,
1126
+ error: he(e)
1127
+ }), e?.code === "daily-limit" && s(0), e?.code === "conversation-not-found" && (b.current = null, a(null));
1128
+ } finally {
1129
+ f.current === o && (f.current = null);
1130
+ }
1131
+ }, [e, C]), T = m(async (t) => {
1132
+ S();
1133
+ let n = p.current;
1134
+ r([]), a(null), d(null), l(!0);
1135
+ try {
1136
+ let i = await e.getConversation(t);
1137
+ if (n !== p.current) return;
1138
+ r(_e(i.messages)), a(i.publicId);
1139
+ } catch (e) {
1140
+ if (n !== p.current) return;
1141
+ d(he(e));
1142
+ } finally {
1143
+ n === p.current && l(!1);
1144
+ }
1145
+ }, [S, e]), E = m(() => {
1146
+ S(), r([]), a(null), d(null), l(!1);
1147
+ }, [S]), D = m(() => {
1148
+ S(), r([]), a(null), s(null), d(null), l(!1);
1149
+ }, [S]), O = m(async () => {
1150
+ let t = p.current, n = await e.getAllowance();
1151
+ t === p.current && s(n?.messagesLeftToday ?? null);
1152
+ }, [e]), k = m(async (t, n, r) => {
1153
+ let i = x.current.find((e) => e.id === t), a = b.current;
1154
+ if (!i?.messageId || !a) throw Error("Only a stored reply can be rated.");
1155
+ let o = {
1156
+ rating: i.rating,
1157
+ ratingNote: i.ratingNote
1158
+ }, s = typeof r == "string" && r.trim() ? r.trim() : null;
1159
+ C(t, {
1160
+ rating: n,
1161
+ ratingNote: s
1162
+ });
1163
+ try {
1164
+ await e.rateMessage(a, i.messageId, {
1165
+ rating: n,
1166
+ note: s
1167
+ });
1168
+ } catch (e) {
1169
+ throw C(t, o), e;
1170
+ }
1171
+ }, [e, C]);
1172
+ return {
1173
+ turns: n,
1174
+ conversationId: i,
1175
+ messagesLeftToday: o,
1176
+ streaming: n.some((e) => e.streaming),
1177
+ loading: c,
1178
+ loadError: u,
1179
+ submit: w,
1180
+ openConversation: T,
1181
+ newConversation: E,
1182
+ rate: k,
1183
+ refreshAllowance: O,
1184
+ reset: D
1185
+ };
1186
+ }
1187
+ //#endregion
1188
+ export { F as ActionCard, w as ChatApiError, I as ChatComposer, re as ChatConversationList, oe as ChatLauncher, X as ChatMarkdown, Q as ChatMessage, me as ChatPanel, $ as ChatThread, j as DEFAULT_CHAT_LABELS, Z as ReplyRating, A as createChatClient, S as createSseParser, ve as useChat };