@eshal-bot/chat-widget 0.1.39 → 0.1.41
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/chat-widget.esm.js +5 -5
- package/dist/chat-widget.js +576 -192
- package/dist/chat-widget.min.js +6 -6
- package/dist/chat-widget.umd.js +5 -5
- package/package.json +1 -1
package/dist/chat-widget.js
CHANGED
|
@@ -8664,94 +8664,102 @@
|
|
|
8664
8664
|
return (_ONBOARDING_FIELD_ORD = ONBOARDING_FIELD_ORDER[key]) !== null && _ONBOARDING_FIELD_ORD !== void 0 ? _ONBOARDING_FIELD_ORD : 99;
|
|
8665
8665
|
};
|
|
8666
8666
|
|
|
8667
|
-
const
|
|
8668
|
-
|
|
8669
|
-
|
|
8670
|
-
|
|
8671
|
-
|
|
8672
|
-
|
|
8673
|
-
|
|
8674
|
-
|
|
8675
|
-
}, config.apiKey && {
|
|
8676
|
-
Authorization: "Bearer ".concat(config.apiKey)
|
|
8677
|
-
}),
|
|
8678
|
-
body: JSON.stringify({
|
|
8679
|
-
userId: config.userId,
|
|
8680
|
-
userName: config.userName,
|
|
8681
|
-
userEmail: config.userEmail
|
|
8682
|
-
}),
|
|
8683
|
-
credentials: "include"
|
|
8684
|
-
});
|
|
8685
|
-
const data = await response.json();
|
|
8686
|
-
return data.sessionId;
|
|
8687
|
-
} catch (error) {
|
|
8688
|
-
console.error("Session creation error:", error);
|
|
8689
|
-
return null;
|
|
8690
|
-
}
|
|
8691
|
-
}
|
|
8692
|
-
return null;
|
|
8693
|
-
};
|
|
8667
|
+
const SESSION_KEY$1 = 'eshal_chat_session';
|
|
8668
|
+
const SESSION_MSG_KEY = 'eshal_chat_session_messages';
|
|
8669
|
+
|
|
8670
|
+
// Defaults used when the deploy-agent payload hasn't resolved yet (first paint
|
|
8671
|
+
// race) or doesn't include `messageLimits` (older backend). The authoritative
|
|
8672
|
+
// values come from the backend via `WIDGET_CONFIG.MESSAGE_LIMITS`.
|
|
8673
|
+
const DEFAULT_MESSAGE_CAP = 200;
|
|
8674
|
+
const DEFAULT_MESSAGE_TRIM_BATCH = 50;
|
|
8694
8675
|
|
|
8695
8676
|
/**
|
|
8696
|
-
*
|
|
8697
|
-
*
|
|
8698
|
-
*
|
|
8699
|
-
*
|
|
8700
|
-
*
|
|
8701
|
-
*/
|
|
8702
|
-
|
|
8703
|
-
|
|
8704
|
-
|
|
8705
|
-
|
|
8706
|
-
|
|
8707
|
-
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
|
|
8711
|
-
|
|
8712
|
-
|
|
8677
|
+
* Sliding-window trim. Once the transcript exceeds `cap`, slice off the
|
|
8678
|
+
* oldest `trimBatch` messages — when both surfaces are at steady state the
|
|
8679
|
+
* loop runs at most once; the `while` is defensive against bursts (e.g. a
|
|
8680
|
+
* voice turn that lands several transcription chunks in one tick) that
|
|
8681
|
+
* push length far past the cap in a single render.
|
|
8682
|
+
*/
|
|
8683
|
+
function applyMessageCap(messages) {
|
|
8684
|
+
let cap = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_MESSAGE_CAP;
|
|
8685
|
+
let trimBatch = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DEFAULT_MESSAGE_TRIM_BATCH;
|
|
8686
|
+
if (!Array.isArray(messages)) return [];
|
|
8687
|
+
if (typeof cap !== 'number' || cap <= 0) cap = DEFAULT_MESSAGE_CAP;
|
|
8688
|
+
if (typeof trimBatch !== 'number' || trimBatch <= 0 || trimBatch >= cap) {
|
|
8689
|
+
trimBatch = Math.min(DEFAULT_MESSAGE_TRIM_BATCH, cap - 1);
|
|
8690
|
+
}
|
|
8691
|
+
let m = messages;
|
|
8692
|
+
while (m.length > cap) m = m.slice(trimBatch);
|
|
8693
|
+
return m;
|
|
8694
|
+
}
|
|
8695
|
+
|
|
8696
|
+
// Strip transient fields (in-flight streaming flags, Date objects) so the
|
|
8697
|
+
// persisted shape is stable across React re-mounts. Keep the bits the UI
|
|
8698
|
+
// needs to render a faithful replay: role + content + timestamp + per-message
|
|
8699
|
+
// metadata (sources, feedback, prompt suggestions, content type).
|
|
8700
|
+
//
|
|
8701
|
+
// The welcome message is INTENTIONALLY excluded. It's client-side display
|
|
8702
|
+
// state generated from `widgetConfig.welcomeMessage` on every mount; the
|
|
8703
|
+
// hydrate path always prepends a fresh welcome above the restored history.
|
|
8704
|
+
// Persisting it would cause a duplicate-welcome render on reload because the
|
|
8705
|
+
// stored copy lacks the `isWelcome` flag (sanitize would strip it) and gets
|
|
8706
|
+
// rendered as a regular assistant message alongside the freshly-added one.
|
|
8707
|
+
function sanitizeMessagesForStorage(messages) {
|
|
8708
|
+
if (!Array.isArray(messages)) return [];
|
|
8709
|
+
return messages.filter(m => m && !m.isWelcome && (m.content || Array.isArray(m.sources) && m.sources.length > 0)).map(m => {
|
|
8710
|
+
var _m$type;
|
|
8711
|
+
return _objectSpread2(_objectSpread2(_objectSpread2({
|
|
8712
|
+
id: m.id,
|
|
8713
|
+
role: m.role,
|
|
8714
|
+
content: m.content,
|
|
8715
|
+
timestamp: m.timestamp instanceof Date ? m.timestamp.toISOString() : typeof m.timestamp === 'string' ? m.timestamp : new Date().toISOString(),
|
|
8716
|
+
type: (_m$type = m.type) !== null && _m$type !== void 0 ? _m$type : null
|
|
8717
|
+
}, Array.isArray(m.sources) && m.sources.length > 0 ? {
|
|
8718
|
+
sources: m.sources
|
|
8719
|
+
} : {}), m.feedback !== undefined ? {
|
|
8720
|
+
feedback: m.feedback
|
|
8721
|
+
} : {}), Array.isArray(m.prompts) && m.prompts.length > 0 ? {
|
|
8722
|
+
prompts: m.prompts
|
|
8723
|
+
} : {});
|
|
8713
8724
|
});
|
|
8714
|
-
|
|
8715
|
-
|
|
8716
|
-
|
|
8717
|
-
|
|
8718
|
-
|
|
8725
|
+
}
|
|
8726
|
+
const saveSessionMessages = (orgId, conversationId, messages, limits) => {
|
|
8727
|
+
if (!orgId || !conversationId) return;
|
|
8728
|
+
try {
|
|
8729
|
+
const cap = limits === null || limits === void 0 ? void 0 : limits.cap;
|
|
8730
|
+
const trimBatch = limits === null || limits === void 0 ? void 0 : limits.trimBatch;
|
|
8731
|
+
const trimmed = applyMessageCap(messages, cap, trimBatch);
|
|
8732
|
+
const sanitized = sanitizeMessagesForStorage(trimmed);
|
|
8733
|
+
localStorage.setItem("".concat(SESSION_MSG_KEY, "_").concat(orgId, "_").concat(conversationId), JSON.stringify(sanitized));
|
|
8734
|
+
} catch (_unused) {
|
|
8735
|
+
// Quota / private-mode / serialization failure — drop silently. The
|
|
8736
|
+
// user-visible chat is unaffected; only the post-reload replay is lost.
|
|
8719
8737
|
}
|
|
8720
|
-
const data = await response.json();
|
|
8721
|
-
return data.messages || [];
|
|
8722
8738
|
};
|
|
8723
|
-
|
|
8724
|
-
|
|
8725
|
-
|
|
8726
|
-
|
|
8727
|
-
|
|
8728
|
-
|
|
8729
|
-
|
|
8730
|
-
|
|
8731
|
-
|
|
8732
|
-
|
|
8739
|
+
const getSessionMessages = (orgId, conversationId) => {
|
|
8740
|
+
if (!orgId || !conversationId) return [];
|
|
8741
|
+
try {
|
|
8742
|
+
const raw = localStorage.getItem("".concat(SESSION_MSG_KEY, "_").concat(orgId, "_").concat(conversationId));
|
|
8743
|
+
if (!raw) return [];
|
|
8744
|
+
const parsed = JSON.parse(raw);
|
|
8745
|
+
if (!Array.isArray(parsed)) return [];
|
|
8746
|
+
// Restore Date objects so MessageList timestamp formatting works without
|
|
8747
|
+
// every downstream consumer doing the conversion itself.
|
|
8748
|
+
return parsed.map(m => _objectSpread2(_objectSpread2({}, m), {}, {
|
|
8749
|
+
timestamp: m.timestamp ? new Date(m.timestamp) : new Date()
|
|
8750
|
+
}));
|
|
8751
|
+
} catch (_unused2) {
|
|
8752
|
+
return [];
|
|
8733
8753
|
}
|
|
8754
|
+
};
|
|
8755
|
+
const clearSessionMessages = (orgId, conversationId) => {
|
|
8756
|
+
if (!orgId || !conversationId) return;
|
|
8734
8757
|
try {
|
|
8735
|
-
|
|
8736
|
-
|
|
8737
|
-
|
|
8738
|
-
headers: {
|
|
8739
|
-
"Content-Type": "application/json"
|
|
8740
|
-
},
|
|
8741
|
-
credentials: "include"
|
|
8742
|
-
});
|
|
8743
|
-
if (!response.ok) {
|
|
8744
|
-
throw new Error("HTTP error! status: ".concat(response.status));
|
|
8745
|
-
}
|
|
8746
|
-
const data = await response.json();
|
|
8747
|
-
return data;
|
|
8748
|
-
} catch (error) {
|
|
8749
|
-
console.error("Failed to fetch agent configuration:", error);
|
|
8750
|
-
throw error;
|
|
8758
|
+
localStorage.removeItem("".concat(SESSION_MSG_KEY, "_").concat(orgId, "_").concat(conversationId));
|
|
8759
|
+
} catch (_unused3) {
|
|
8760
|
+
// ignore
|
|
8751
8761
|
}
|
|
8752
8762
|
};
|
|
8753
|
-
|
|
8754
|
-
const SESSION_KEY$1 = 'eshal_chat_session';
|
|
8755
8763
|
const getTimeoutMs = (value, unit) => {
|
|
8756
8764
|
if (value === undefined || value === null || !unit) return null;
|
|
8757
8765
|
const multipliers = {
|
|
@@ -8772,7 +8780,7 @@
|
|
|
8772
8780
|
const raw = localStorage.getItem("".concat(SESSION_KEY$1, "_").concat(orgId));
|
|
8773
8781
|
if (!raw) return null;
|
|
8774
8782
|
return JSON.parse(raw);
|
|
8775
|
-
} catch (
|
|
8783
|
+
} catch (_unused4) {
|
|
8776
8784
|
return null;
|
|
8777
8785
|
}
|
|
8778
8786
|
};
|
|
@@ -8822,7 +8830,7 @@
|
|
|
8822
8830
|
createdAt: now,
|
|
8823
8831
|
firstInteractionAt: null
|
|
8824
8832
|
}, extra)));
|
|
8825
|
-
} catch (
|
|
8833
|
+
} catch (_unused5) {}
|
|
8826
8834
|
};
|
|
8827
8835
|
const updateActivity = orgId => {
|
|
8828
8836
|
try {
|
|
@@ -8836,7 +8844,7 @@
|
|
|
8836
8844
|
session.firstInteractionAt = now;
|
|
8837
8845
|
}
|
|
8838
8846
|
localStorage.setItem("".concat(SESSION_KEY$1, "_").concat(orgId), JSON.stringify(session));
|
|
8839
|
-
} catch (
|
|
8847
|
+
} catch (_unused6) {}
|
|
8840
8848
|
};
|
|
8841
8849
|
const markOnboardingCompleted = orgId => {
|
|
8842
8850
|
try {
|
|
@@ -8844,7 +8852,7 @@
|
|
|
8844
8852
|
if (!session) return;
|
|
8845
8853
|
session.onboardingCompleted = true;
|
|
8846
8854
|
localStorage.setItem("".concat(SESSION_KEY$1, "_").concat(orgId), JSON.stringify(session));
|
|
8847
|
-
} catch (
|
|
8855
|
+
} catch (_unused7) {}
|
|
8848
8856
|
};
|
|
8849
8857
|
const markCsatSubmitted = orgId => {
|
|
8850
8858
|
try {
|
|
@@ -8852,12 +8860,21 @@
|
|
|
8852
8860
|
if (!session) return;
|
|
8853
8861
|
session.csatSubmitted = true;
|
|
8854
8862
|
localStorage.setItem("".concat(SESSION_KEY$1, "_").concat(orgId), JSON.stringify(session));
|
|
8855
|
-
} catch (
|
|
8863
|
+
} catch (_unused8) {}
|
|
8856
8864
|
};
|
|
8857
8865
|
const clearSession$2 = orgId => {
|
|
8858
8866
|
try {
|
|
8867
|
+
// Read the session BEFORE removing it so we know which messages bucket to
|
|
8868
|
+
// clear. Inactivity sweepers / explicit resets call this path; leaving the
|
|
8869
|
+
// messages bucket behind would resurrect the prior transcript when a new
|
|
8870
|
+
// session happens to land on the same conversationId (extremely rare, but
|
|
8871
|
+
// free to defend against).
|
|
8872
|
+
const existing = getSession(orgId);
|
|
8859
8873
|
localStorage.removeItem("".concat(SESSION_KEY$1, "_").concat(orgId));
|
|
8860
|
-
|
|
8874
|
+
if (existing !== null && existing !== void 0 && existing.conversationId) {
|
|
8875
|
+
clearSessionMessages(orgId, existing.conversationId);
|
|
8876
|
+
}
|
|
8877
|
+
} catch (_unused9) {}
|
|
8861
8878
|
};
|
|
8862
8879
|
const savePromptSuggestions = (orgId, prompts) => {
|
|
8863
8880
|
try {
|
|
@@ -8867,14 +8884,14 @@
|
|
|
8867
8884
|
return;
|
|
8868
8885
|
}
|
|
8869
8886
|
localStorage.setItem("".concat(SESSION_KEY$1, "_prompts_").concat(orgId), JSON.stringify(prompts));
|
|
8870
|
-
} catch (
|
|
8887
|
+
} catch (_unused0) {}
|
|
8871
8888
|
};
|
|
8872
8889
|
const getPromptSuggestions = orgId => {
|
|
8873
8890
|
try {
|
|
8874
8891
|
const raw = localStorage.getItem("".concat(SESSION_KEY$1, "_prompts_").concat(orgId));
|
|
8875
8892
|
if (!raw) return [];
|
|
8876
8893
|
return JSON.parse(raw) || [];
|
|
8877
|
-
} catch (
|
|
8894
|
+
} catch (_unused1) {
|
|
8878
8895
|
return [];
|
|
8879
8896
|
}
|
|
8880
8897
|
};
|
|
@@ -8920,8 +8937,17 @@
|
|
|
8920
8937
|
onboardingEnabled = false,
|
|
8921
8938
|
collectionPrompt,
|
|
8922
8939
|
inactivityTimeoutValue,
|
|
8923
|
-
inactivityTimeoutUnit
|
|
8940
|
+
inactivityTimeoutUnit,
|
|
8941
|
+
// Sliding-window limits for the persisted transcript. Sourced from the
|
|
8942
|
+
// backend's `messageLimits` field on the deploy-agent payload so per-env
|
|
8943
|
+
// configuration ships through one channel. Falls back to module defaults
|
|
8944
|
+
// during the brief mount window before the deploy-agent fetch resolves.
|
|
8945
|
+
messageLimits
|
|
8924
8946
|
} = _ref2;
|
|
8947
|
+
const resolvedMessageLimits = reactExports.useMemo(() => ({
|
|
8948
|
+
cap: typeof (messageLimits === null || messageLimits === void 0 ? void 0 : messageLimits.cap) === 'number' && messageLimits.cap > 0 ? messageLimits.cap : DEFAULT_MESSAGE_CAP,
|
|
8949
|
+
trimBatch: typeof (messageLimits === null || messageLimits === void 0 ? void 0 : messageLimits.trimBatch) === 'number' && messageLimits.trimBatch > 0 ? messageLimits.trimBatch : DEFAULT_MESSAGE_TRIM_BATCH
|
|
8950
|
+
}), [messageLimits === null || messageLimits === void 0 ? void 0 : messageLimits.cap, messageLimits === null || messageLimits === void 0 ? void 0 : messageLimits.trimBatch]);
|
|
8925
8951
|
const [isOpen, setIsOpen] = reactExports.useState(autoOpen);
|
|
8926
8952
|
const [isMinimized, setIsMinimized] = reactExports.useState(false);
|
|
8927
8953
|
const [isDark, setIsDark] = reactExports.useState(darkMode);
|
|
@@ -9140,91 +9166,62 @@
|
|
|
9140
9166
|
return;
|
|
9141
9167
|
}
|
|
9142
9168
|
|
|
9143
|
-
// Restore session —
|
|
9144
|
-
|
|
9169
|
+
// Restore session — hydrate from localStorage only. We no longer hit
|
|
9170
|
+
// `GET /api/v1/conversations/:orgId/:conversationId` because orgs with
|
|
9171
|
+
// the Eshal Inbox conversation route turned OFF never get rows written
|
|
9172
|
+
// (`isInboxRouteEnabled` gates persistence) and the empty backend reply
|
|
9173
|
+
// was wiping the on-screen transcript on every reload. localStorage is
|
|
9174
|
+
// now the only source of session replay; inbox-on orgs still see their
|
|
9175
|
+
// full transcript because every settled message is mirrored locally.
|
|
9176
|
+
if (!historyLoadedRef.current) {
|
|
9145
9177
|
historyLoadedRef.current = true;
|
|
9146
|
-
|
|
9147
|
-
|
|
9148
|
-
|
|
9149
|
-
|
|
9150
|
-
|
|
9151
|
-
|
|
9152
|
-
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
|
|
9156
|
-
|
|
9157
|
-
const
|
|
9158
|
-
|
|
9159
|
-
|
|
9160
|
-
|
|
9161
|
-
|
|
9162
|
-
|
|
9163
|
-
|
|
9164
|
-
return {
|
|
9165
|
-
source_type: (_ref3 = (_s$source_type = s.source_type) !== null && _s$source_type !== void 0 ? _s$source_type : s.sourceType) !== null && _ref3 !== void 0 ? _ref3 : 'website',
|
|
9166
|
-
source_id: (_s$source_id = s.source_id) !== null && _s$source_id !== void 0 ? _s$source_id : s.sourceid,
|
|
9167
|
-
source_name: (_ref4 = (_s$source_name = s.source_name) !== null && _s$source_name !== void 0 ? _s$source_name : s.sourceName) !== null && _ref4 !== void 0 ? _ref4 : '',
|
|
9168
|
-
url: s.url
|
|
9169
|
-
};
|
|
9170
|
-
}).filter(s => s.source_id || s.url) : [];
|
|
9171
|
-
return _objectSpread2(_objectSpread2(_objectSpread2({}, createMessage({
|
|
9172
|
-
id: msg.id || "history-".concat(index, "-").concat(Date.now()),
|
|
9173
|
-
role: msg.role || (msg.sender === 'user' ? 'user' : 'assistant'),
|
|
9174
|
-
content: msg.message || msg.content || ''
|
|
9175
|
-
})), {}, {
|
|
9176
|
-
timestamp: msg.time ? new Date(msg.time) : new Date()
|
|
9177
|
-
}, Array.isArray(msg.prompts) && msg.prompts.length > 0 ? {
|
|
9178
|
-
prompts: msg.prompts
|
|
9179
|
-
} : {}), sources.length > 0 ? {
|
|
9180
|
-
sources
|
|
9181
|
-
} : {});
|
|
9178
|
+
const stored = getSessionMessages(organizationId, bidiSessionId);
|
|
9179
|
+
if (stored.length > 0) {
|
|
9180
|
+
historyHasMessagesRef.current = true;
|
|
9181
|
+
// Prepend the welcome message so reloads still lead with it,
|
|
9182
|
+
// matching the pre-localStorage replay behaviour. The welcome
|
|
9183
|
+
// message is client-only, never written to the messages bucket,
|
|
9184
|
+
// so it needs to be reattached on every hydrate.
|
|
9185
|
+
if (welcomeMessage) {
|
|
9186
|
+
var _stored$;
|
|
9187
|
+
const firstTs = (_stored$ = stored[0]) === null || _stored$ === void 0 ? void 0 : _stored$.timestamp;
|
|
9188
|
+
const firstTsMs = firstTs instanceof Date ? firstTs.getTime() : firstTs ? new Date(firstTs).getTime() : Date.now();
|
|
9189
|
+
const welcomeMsg = _objectSpread2(_objectSpread2({}, createMessage({
|
|
9190
|
+
id: 'welcome-restored',
|
|
9191
|
+
role: 'assistant',
|
|
9192
|
+
content: welcomeMessage
|
|
9193
|
+
})), {}, {
|
|
9194
|
+
isWelcome: true,
|
|
9195
|
+
timestamp: new Date(firstTsMs - 1)
|
|
9182
9196
|
});
|
|
9197
|
+
setMessages([welcomeMsg, ...stored]);
|
|
9198
|
+
} else {
|
|
9199
|
+
setMessages(stored);
|
|
9200
|
+
}
|
|
9183
9201
|
|
|
9184
|
-
|
|
9185
|
-
|
|
9186
|
-
|
|
9187
|
-
|
|
9188
|
-
|
|
9189
|
-
|
|
9190
|
-
|
|
9191
|
-
|
|
9192
|
-
|
|
9202
|
+
// If no message in the restored transcript carries prompt
|
|
9203
|
+
// suggestions, fall back to the legacy per-org bucket. Preserves
|
|
9204
|
+
// the "prompts survive refresh" UX even when the persistence layer
|
|
9205
|
+
// hasn't seen an assistant turn yet.
|
|
9206
|
+
const hasAnyPrompts = stored.some(m => m.role === 'assistant' && Array.isArray(m.prompts) && m.prompts.length > 0);
|
|
9207
|
+
if (!hasAnyPrompts) {
|
|
9208
|
+
const savedPrompts = getPromptSuggestions(organizationId);
|
|
9209
|
+
if (savedPrompts.length > 0) {
|
|
9210
|
+
setMessages(prev => {
|
|
9211
|
+
const next = [...prev];
|
|
9212
|
+
for (let i = next.length - 1; i >= 0; i -= 1) {
|
|
9213
|
+
if (next[i].role === 'assistant') {
|
|
9214
|
+
next[i] = _objectSpread2(_objectSpread2({}, next[i]), {}, {
|
|
9193
9215
|
prompts: savedPrompts
|
|
9194
9216
|
});
|
|
9195
9217
|
break;
|
|
9196
9218
|
}
|
|
9197
9219
|
}
|
|
9198
|
-
|
|
9199
|
-
}
|
|
9200
|
-
|
|
9201
|
-
// Always prepend the welcome message so it shows at the top after refresh,
|
|
9202
|
-
// matching chatbot-preview behaviour (welcome message is client-side only
|
|
9203
|
-
// and is not stored in server history).
|
|
9204
|
-
// Use a timestamp before the first history message so it sorts first
|
|
9205
|
-
// (activeMessages is sorted by timestamp before being passed to the UI).
|
|
9206
|
-
if (welcomeMessage) {
|
|
9207
|
-
var _historyMessages$;
|
|
9208
|
-
const firstTs = (_historyMessages$ = historyMessages[0]) === null || _historyMessages$ === void 0 ? void 0 : _historyMessages$.timestamp;
|
|
9209
|
-
const firstTsMs = firstTs instanceof Date ? firstTs.getTime() : firstTs ? new Date(firstTs).getTime() : Date.now();
|
|
9210
|
-
const welcomeMsg = _objectSpread2(_objectSpread2({}, createMessage({
|
|
9211
|
-
id: 'welcome-restored',
|
|
9212
|
-
role: 'assistant',
|
|
9213
|
-
content: welcomeMessage
|
|
9214
|
-
})), {}, {
|
|
9215
|
-
isWelcome: true,
|
|
9216
|
-
timestamp: new Date(firstTsMs - 1)
|
|
9220
|
+
return next;
|
|
9217
9221
|
});
|
|
9218
|
-
setMessages([welcomeMsg, ...historyMessages]);
|
|
9219
|
-
} else {
|
|
9220
|
-
setMessages(historyMessages);
|
|
9221
9222
|
}
|
|
9222
9223
|
}
|
|
9223
|
-
}
|
|
9224
|
-
console.error('[Session] History fetch failed:', err);
|
|
9225
|
-
}).finally(() => {
|
|
9226
|
-
setIsConversationLoading(false);
|
|
9227
|
-
});
|
|
9224
|
+
}
|
|
9228
9225
|
}
|
|
9229
9226
|
} else {
|
|
9230
9227
|
// Session is expired, invalid, or non-existent
|
|
@@ -9236,9 +9233,27 @@
|
|
|
9236
9233
|
if (existing && bidiSessionId === existing.conversationId) {
|
|
9237
9234
|
const newId = "widget-session-".concat(Math.random().toString(36).slice(2, 9));
|
|
9238
9235
|
console.warn("[Session] Rotating expired ID ".concat(bidiSessionId, " -> ").concat(newId));
|
|
9236
|
+
// Drop the expired conversation's localStorage transcript before
|
|
9237
|
+
// rotating — otherwise the bucket sticks around forever (the key
|
|
9238
|
+
// includes the conversationId, so it'd never get hit again but
|
|
9239
|
+
// would still occupy origin storage on the customer's site).
|
|
9240
|
+
clearSessionMessages(organizationId, bidiSessionId);
|
|
9239
9241
|
setBidiSessionId(newId);
|
|
9240
9242
|
// Note: saveSession will be called on the next run with the newId
|
|
9241
9243
|
} else {
|
|
9244
|
+
// Cold-start cleanup: the `useState` initializer above generates a
|
|
9245
|
+
// FRESH `bidiSessionId` when it can't reuse the stored session (timeout
|
|
9246
|
+
// expired before reload, settings snapshot mismatched, or the deploy-
|
|
9247
|
+
// agent payload was still loading at first paint so it couldn't run
|
|
9248
|
+
// `isSessionValid`). In that case `existing.conversationId` points to
|
|
9249
|
+
// a now-stale conversation whose messages bucket would otherwise be
|
|
9250
|
+
// orphaned forever — `clearSession` runs in `resetConversation` (which
|
|
9251
|
+
// we never hit here) and the rotate-id branch above only fires when
|
|
9252
|
+
// the IDs match. Mirror the frontend `useSessionManager` hydrate
|
|
9253
|
+
// effect: clean up the stale bucket before we save the new session.
|
|
9254
|
+
if (existing !== null && existing !== void 0 && existing.conversationId && existing.conversationId !== bidiSessionId) {
|
|
9255
|
+
clearSessionMessages(organizationId, existing.conversationId);
|
|
9256
|
+
}
|
|
9242
9257
|
// We have a fresh ID (either from initializer or rotation), persist it if not already there
|
|
9243
9258
|
if (!existing || existing.conversationId !== bidiSessionId) {
|
|
9244
9259
|
saveSession(organizationId, bidiSessionId, {
|
|
@@ -9264,6 +9279,29 @@
|
|
|
9264
9279
|
}
|
|
9265
9280
|
}, [messages, organizationId]);
|
|
9266
9281
|
|
|
9282
|
+
// ── Sliding-window trim: drop the oldest TRIM_BATCH messages when state
|
|
9283
|
+
// exceeds CAP. Runs only when no message is mid-stream so we never slice
|
|
9284
|
+
// through a partial assistant token. Mutates React state (matches the
|
|
9285
|
+
// intended UX — old scrollback drops in front of the user once the cap is
|
|
9286
|
+
// hit, keeping what's on screen identical to what's in localStorage).
|
|
9287
|
+
reactExports.useEffect(() => {
|
|
9288
|
+
if (isConversationLoading || isLoading) return;
|
|
9289
|
+
if (messages.length <= resolvedMessageLimits.cap) return;
|
|
9290
|
+
setMessages(prev => applyMessageCap(prev, resolvedMessageLimits.cap, resolvedMessageLimits.trimBatch));
|
|
9291
|
+
}, [messages.length, isConversationLoading, isLoading, resolvedMessageLimits.cap, resolvedMessageLimits.trimBatch]);
|
|
9292
|
+
|
|
9293
|
+
// ── Persist a settled snapshot of the transcript. We write only when
|
|
9294
|
+
// streaming/voice traffic has quiesced so a partial assistant message
|
|
9295
|
+
// never lands in localStorage — on reload the next snapshot will reflect
|
|
9296
|
+
// the completed turn. Skipped while history is hydrating (initial mount
|
|
9297
|
+
// race) so the first restore isn't immediately overwritten by an empty
|
|
9298
|
+
// pre-hydrate state.
|
|
9299
|
+
reactExports.useEffect(() => {
|
|
9300
|
+
if (!organizationId || !bidiSessionId) return;
|
|
9301
|
+
if (isConversationLoading || isLoading) return;
|
|
9302
|
+
saveSessionMessages(organizationId, bidiSessionId, messages, resolvedMessageLimits);
|
|
9303
|
+
}, [messages, organizationId, bidiSessionId, isConversationLoading, isLoading, resolvedMessageLimits]);
|
|
9304
|
+
|
|
9267
9305
|
// Show the onboarding form on first load; bypass it if already completed (persisted in session)
|
|
9268
9306
|
reactExports.useEffect(() => {
|
|
9269
9307
|
if (!onboardingEnabled || onboardingCompleted) return;
|
|
@@ -10252,11 +10290,11 @@
|
|
|
10252
10290
|
const rawSources = (_event$sources = event.sources) !== null && _event$sources !== void 0 ? _event$sources : event.Sources;
|
|
10253
10291
|
if (Array.isArray(rawSources) && rawSources.length > 0) {
|
|
10254
10292
|
const normalizedSources = rawSources.map(s => {
|
|
10255
|
-
var
|
|
10293
|
+
var _ref3, _s$source_type, _ref4, _s$source_id, _ref5, _s$source_name;
|
|
10256
10294
|
return {
|
|
10257
|
-
source_type: (
|
|
10258
|
-
source_id: (
|
|
10259
|
-
source_name: (
|
|
10295
|
+
source_type: (_ref3 = (_s$source_type = s.source_type) !== null && _s$source_type !== void 0 ? _s$source_type : s.sourceType) !== null && _ref3 !== void 0 ? _ref3 : 'file',
|
|
10296
|
+
source_id: (_ref4 = (_s$source_id = s.source_id) !== null && _s$source_id !== void 0 ? _s$source_id : s.sourceid) !== null && _ref4 !== void 0 ? _ref4 : s.sourceId,
|
|
10297
|
+
source_name: (_ref5 = (_s$source_name = s.source_name) !== null && _s$source_name !== void 0 ? _s$source_name : s.sourceName) !== null && _ref5 !== void 0 ? _ref5 : '',
|
|
10260
10298
|
url: s.url
|
|
10261
10299
|
};
|
|
10262
10300
|
}).filter(s => s.source_id || s.url);
|
|
@@ -10563,6 +10601,10 @@
|
|
|
10563
10601
|
setMessages([]);
|
|
10564
10602
|
setBidiMessages([]);
|
|
10565
10603
|
|
|
10604
|
+
// Drop the localStorage transcript for the conversation we're abandoning
|
|
10605
|
+
// BEFORE we rotate to a fresh sessionId, otherwise the old bucket leaks.
|
|
10606
|
+
clearSessionMessages(organizationId, bidiSessionId);
|
|
10607
|
+
|
|
10566
10608
|
// Reset onboarding
|
|
10567
10609
|
setOnboardingActive(false);
|
|
10568
10610
|
setOnboardingCompleted(false);
|
|
@@ -10601,7 +10643,7 @@
|
|
|
10601
10643
|
setOnboardingActive(true);
|
|
10602
10644
|
}
|
|
10603
10645
|
}
|
|
10604
|
-
}, [organizationId, welcomeMessage, onboardingEnabled, onboardingQuestions]);
|
|
10646
|
+
}, [organizationId, bidiSessionId, welcomeMessage, onboardingEnabled, onboardingQuestions, inactivityTimeoutValue, inactivityTimeoutUnit]);
|
|
10605
10647
|
|
|
10606
10648
|
// Keep a stable ref to resetConversation so the timer effect does not need to
|
|
10607
10649
|
// list it as a dependency (avoids spurious re-runs — and spurious updateActivity
|
|
@@ -56065,6 +56107,12 @@
|
|
|
56065
56107
|
const DICTIONARIES = {
|
|
56066
56108
|
en: EN,
|
|
56067
56109
|
ar: {
|
|
56110
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56111
|
+
// substituted verbatim at the call site and rendered through
|
|
56112
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56113
|
+
chooseTopicLabel: "اختر موضوعًا للبدء:",
|
|
56114
|
+
categoryTopicsHeading: "يرجى طرح سؤالك حول **{category}** أدناه.",
|
|
56115
|
+
quickQuestionsHeadingLabel: "أو اطرح سؤالًا سريعًا:",
|
|
56068
56116
|
typeYourMessage: "اكتب رسالتك هنا...",
|
|
56069
56117
|
agentIsLoading: "جارٍ تحميل الوكيل...",
|
|
56070
56118
|
conversationResolved: "تم إنهاء المحادثة",
|
|
@@ -56097,6 +56145,12 @@
|
|
|
56097
56145
|
allowMicAccess: "السماح بالوصول إلى الميكروفون"
|
|
56098
56146
|
},
|
|
56099
56147
|
es: {
|
|
56148
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56149
|
+
// substituted verbatim at the call site and rendered through
|
|
56150
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56151
|
+
chooseTopicLabel: "Elige un tema para empezar:",
|
|
56152
|
+
categoryTopicsHeading: "Por favor, haz tu pregunta sobre **{category}** a continuación.",
|
|
56153
|
+
quickQuestionsHeadingLabel: "O haz una pregunta rápida:",
|
|
56100
56154
|
typeYourMessage: "Escribe tu mensaje...",
|
|
56101
56155
|
agentIsLoading: "El agente está cargando...",
|
|
56102
56156
|
conversationResolved: "Conversación resuelta",
|
|
@@ -56129,6 +56183,12 @@
|
|
|
56129
56183
|
allowMicAccess: "Permitir acceso al micrófono"
|
|
56130
56184
|
},
|
|
56131
56185
|
be: {
|
|
56186
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56187
|
+
// substituted verbatim at the call site and rendered through
|
|
56188
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56189
|
+
chooseTopicLabel: "Выберыце тэму, каб пачаць:",
|
|
56190
|
+
categoryTopicsHeading: "Калі ласка, задайце сваё пытанне пра **{category}** ніжэй.",
|
|
56191
|
+
quickQuestionsHeadingLabel: "Або задайце хуткае пытанне:",
|
|
56132
56192
|
typeYourMessage: "Увядзіце паведамленне...",
|
|
56133
56193
|
agentIsLoading: "Агент загружаецца...",
|
|
56134
56194
|
conversationResolved: "Размова завершана",
|
|
@@ -56161,6 +56221,12 @@
|
|
|
56161
56221
|
allowMicAccess: "Дазволіць доступ да мікрафона"
|
|
56162
56222
|
},
|
|
56163
56223
|
bs: {
|
|
56224
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56225
|
+
// substituted verbatim at the call site and rendered through
|
|
56226
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56227
|
+
chooseTopicLabel: "Odaberite temu za početak:",
|
|
56228
|
+
categoryTopicsHeading: "Molimo postavite svoje pitanje o **{category}** ispod.",
|
|
56229
|
+
quickQuestionsHeadingLabel: "Ili postavite brzo pitanje:",
|
|
56164
56230
|
typeYourMessage: "Upišite vašu poruku...",
|
|
56165
56231
|
agentIsLoading: "Agent se učitava...",
|
|
56166
56232
|
conversationResolved: "Razgovor je završen",
|
|
@@ -56193,6 +56259,12 @@
|
|
|
56193
56259
|
allowMicAccess: "Dozvoli pristup mikrofonu"
|
|
56194
56260
|
},
|
|
56195
56261
|
bg: {
|
|
56262
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56263
|
+
// substituted verbatim at the call site and rendered through
|
|
56264
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56265
|
+
chooseTopicLabel: "Изберете тема, за да започнете:",
|
|
56266
|
+
categoryTopicsHeading: "Моля, задайте въпроса си за **{category}** по-долу.",
|
|
56267
|
+
quickQuestionsHeadingLabel: "Или задайте бърз въпрос:",
|
|
56196
56268
|
typeYourMessage: "Въведете съобщението си...",
|
|
56197
56269
|
agentIsLoading: "Агентът се зарежда...",
|
|
56198
56270
|
conversationResolved: "Разговорът е приключен",
|
|
@@ -56225,6 +56297,12 @@
|
|
|
56225
56297
|
allowMicAccess: "Позволете достъп до микрофона"
|
|
56226
56298
|
},
|
|
56227
56299
|
my: {
|
|
56300
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56301
|
+
// substituted verbatim at the call site and rendered through
|
|
56302
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56303
|
+
chooseTopicLabel: "စတင်ရန် ခေါင်းစဉ်တစ်ခု ရွေးချယ်ပါ:",
|
|
56304
|
+
categoryTopicsHeading: "ကျေးဇူးပြု၍ သင်၏ **{category}** မေးခွန်းကို အောက်တွင် မေးပါ။",
|
|
56305
|
+
quickQuestionsHeadingLabel: "သို့မဟုတ် မြန်ဆန်သော မေးခွန်းတစ်ခု မေးပါ:",
|
|
56228
56306
|
typeYourMessage: "သင့်မက်ဆေ့ချ်ကို ရိုက်ထည့်ပါ...",
|
|
56229
56307
|
agentIsLoading: "အေးဂျင့်ကို ဖွင့်နေသည်...",
|
|
56230
56308
|
conversationResolved: "စကားဝိုင်း ပြီးစီးပြီ",
|
|
@@ -56257,6 +56335,12 @@
|
|
|
56257
56335
|
allowMicAccess: "မိုက်ခရိုဖုန်း ဝင်ရောက်ခွင့်ပြုပါ"
|
|
56258
56336
|
},
|
|
56259
56337
|
ca: {
|
|
56338
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56339
|
+
// substituted verbatim at the call site and rendered through
|
|
56340
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56341
|
+
chooseTopicLabel: "Tria un tema per començar:",
|
|
56342
|
+
categoryTopicsHeading: "Si us plau, fes la teva pregunta sobre **{category}** a continuació.",
|
|
56343
|
+
quickQuestionsHeadingLabel: "O fes una pregunta ràpida:",
|
|
56260
56344
|
typeYourMessage: "Escriu el teu missatge...",
|
|
56261
56345
|
agentIsLoading: "L'agent està carregant...",
|
|
56262
56346
|
conversationResolved: "Conversa resolta",
|
|
@@ -56289,6 +56373,12 @@
|
|
|
56289
56373
|
allowMicAccess: "Permetre accés al micròfon"
|
|
56290
56374
|
},
|
|
56291
56375
|
zh: {
|
|
56376
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56377
|
+
// substituted verbatim at the call site and rendered through
|
|
56378
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56379
|
+
chooseTopicLabel: "选择一个主题开始:",
|
|
56380
|
+
categoryTopicsHeading: "请在下方提出您关于 **{category}** 的问题。",
|
|
56381
|
+
quickQuestionsHeadingLabel: "或者提一个快速问题:",
|
|
56292
56382
|
typeYourMessage: "输入您的消息...",
|
|
56293
56383
|
agentIsLoading: "客服正在加载...",
|
|
56294
56384
|
conversationResolved: "对话已结束",
|
|
@@ -56321,6 +56411,12 @@
|
|
|
56321
56411
|
allowMicAccess: "允许访问麦克风"
|
|
56322
56412
|
},
|
|
56323
56413
|
hr: {
|
|
56414
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56415
|
+
// substituted verbatim at the call site and rendered through
|
|
56416
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56417
|
+
chooseTopicLabel: "Odaberite temu za početak:",
|
|
56418
|
+
categoryTopicsHeading: "Molimo postavite svoje pitanje o **{category}** u nastavku.",
|
|
56419
|
+
quickQuestionsHeadingLabel: "Ili postavite brzo pitanje:",
|
|
56324
56420
|
typeYourMessage: "Upišite svoju poruku...",
|
|
56325
56421
|
agentIsLoading: "Agent se učitava...",
|
|
56326
56422
|
conversationResolved: "Razgovor je završen",
|
|
@@ -56353,6 +56449,12 @@
|
|
|
56353
56449
|
allowMicAccess: "Dopustite pristup mikrofonu"
|
|
56354
56450
|
},
|
|
56355
56451
|
cs: {
|
|
56452
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56453
|
+
// substituted verbatim at the call site and rendered through
|
|
56454
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56455
|
+
chooseTopicLabel: "Vyberte téma a začněte:",
|
|
56456
|
+
categoryTopicsHeading: "Prosím, položte svou otázku ohledně **{category}** níže.",
|
|
56457
|
+
quickQuestionsHeadingLabel: "Nebo položte rychlou otázku:",
|
|
56356
56458
|
typeYourMessage: "Napište zprávu...",
|
|
56357
56459
|
agentIsLoading: "Agent se načítá...",
|
|
56358
56460
|
conversationResolved: "Konverzace ukončena",
|
|
@@ -56385,6 +56487,12 @@
|
|
|
56385
56487
|
allowMicAccess: "Povolit přístup k mikrofonu"
|
|
56386
56488
|
},
|
|
56387
56489
|
da: {
|
|
56490
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56491
|
+
// substituted verbatim at the call site and rendered through
|
|
56492
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56493
|
+
chooseTopicLabel: "Vælg et emne for at komme i gang:",
|
|
56494
|
+
categoryTopicsHeading: "Stil venligst dit spørgsmål om **{category}** nedenfor.",
|
|
56495
|
+
quickQuestionsHeadingLabel: "Eller stil et hurtigt spørgsmål:",
|
|
56388
56496
|
typeYourMessage: "Skriv din besked...",
|
|
56389
56497
|
agentIsLoading: "Agenten indlæses...",
|
|
56390
56498
|
conversationResolved: "Samtale afsluttet",
|
|
@@ -56417,6 +56525,12 @@
|
|
|
56417
56525
|
allowMicAccess: "Tillad mikrofonadgang"
|
|
56418
56526
|
},
|
|
56419
56527
|
nl: {
|
|
56528
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56529
|
+
// substituted verbatim at the call site and rendered through
|
|
56530
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56531
|
+
chooseTopicLabel: "Kies een onderwerp om te beginnen:",
|
|
56532
|
+
categoryTopicsHeading: "Stel hieronder uw vraag over **{category}**.",
|
|
56533
|
+
quickQuestionsHeadingLabel: "Of stel een snelle vraag:",
|
|
56420
56534
|
typeYourMessage: "Typ je bericht...",
|
|
56421
56535
|
agentIsLoading: "Agent wordt geladen...",
|
|
56422
56536
|
conversationResolved: "Gesprek beëindigd",
|
|
@@ -56449,6 +56563,12 @@
|
|
|
56449
56563
|
allowMicAccess: "Toegang tot microfoon toestaan"
|
|
56450
56564
|
},
|
|
56451
56565
|
et: {
|
|
56566
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56567
|
+
// substituted verbatim at the call site and rendered through
|
|
56568
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56569
|
+
chooseTopicLabel: "Vali alustamiseks teema:",
|
|
56570
|
+
categoryTopicsHeading: "Palun esita oma **{category}** küsimus allpool.",
|
|
56571
|
+
quickQuestionsHeadingLabel: "Või esita kiire küsimus:",
|
|
56452
56572
|
typeYourMessage: "Sisesta oma sõnum...",
|
|
56453
56573
|
agentIsLoading: "Agent laeb...",
|
|
56454
56574
|
conversationResolved: "Vestlus lõpetatud",
|
|
@@ -56481,6 +56601,12 @@
|
|
|
56481
56601
|
allowMicAccess: "Luba mikrofoni juurdepääs"
|
|
56482
56602
|
},
|
|
56483
56603
|
fi: {
|
|
56604
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56605
|
+
// substituted verbatim at the call site and rendered through
|
|
56606
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56607
|
+
chooseTopicLabel: "Aloita valitsemalla aihe:",
|
|
56608
|
+
categoryTopicsHeading: "Esitä **{category}**-kysymyksesi alla.",
|
|
56609
|
+
quickQuestionsHeadingLabel: "Tai esitä nopea kysymys:",
|
|
56484
56610
|
typeYourMessage: "Kirjoita viestisi...",
|
|
56485
56611
|
agentIsLoading: "Agenttia ladataan...",
|
|
56486
56612
|
conversationResolved: "Keskustelu päättynyt",
|
|
@@ -56513,6 +56639,12 @@
|
|
|
56513
56639
|
allowMicAccess: "Salli mikrofonin käyttö"
|
|
56514
56640
|
},
|
|
56515
56641
|
fr: {
|
|
56642
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56643
|
+
// substituted verbatim at the call site and rendered through
|
|
56644
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56645
|
+
chooseTopicLabel: "Choisissez un sujet pour commencer :",
|
|
56646
|
+
categoryTopicsHeading: "Veuillez poser votre question sur **{category}** ci-dessous.",
|
|
56647
|
+
quickQuestionsHeadingLabel: "Ou posez une question rapide :",
|
|
56516
56648
|
typeYourMessage: "Tapez votre message...",
|
|
56517
56649
|
agentIsLoading: "L'agent est en cours de chargement...",
|
|
56518
56650
|
conversationResolved: "Conversation terminée",
|
|
@@ -56545,6 +56677,12 @@
|
|
|
56545
56677
|
allowMicAccess: "Autoriser l'accès au microphone"
|
|
56546
56678
|
},
|
|
56547
56679
|
de: {
|
|
56680
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56681
|
+
// substituted verbatim at the call site and rendered through
|
|
56682
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56683
|
+
chooseTopicLabel: "Wählen Sie ein Thema, um zu beginnen:",
|
|
56684
|
+
categoryTopicsHeading: "Bitte stellen Sie Ihre Frage zu **{category}** unten.",
|
|
56685
|
+
quickQuestionsHeadingLabel: "Oder stellen Sie eine schnelle Frage:",
|
|
56548
56686
|
typeYourMessage: "Geben Sie Ihre Nachricht ein...",
|
|
56549
56687
|
agentIsLoading: "Agent wird geladen...",
|
|
56550
56688
|
conversationResolved: "Gespräch beendet",
|
|
@@ -56577,6 +56715,12 @@
|
|
|
56577
56715
|
allowMicAccess: "Mikrofonzugriff erlauben"
|
|
56578
56716
|
},
|
|
56579
56717
|
el: {
|
|
56718
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56719
|
+
// substituted verbatim at the call site and rendered through
|
|
56720
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56721
|
+
chooseTopicLabel: "Επιλέξτε ένα θέμα για να ξεκινήσετε:",
|
|
56722
|
+
categoryTopicsHeading: "Παρακαλώ κάντε την ερώτησή σας σχετικά με το **{category}** παρακάτω.",
|
|
56723
|
+
quickQuestionsHeadingLabel: "Ή κάντε μια γρήγορη ερώτηση:",
|
|
56580
56724
|
typeYourMessage: "Πληκτρολογήστε το μήνυμά σας...",
|
|
56581
56725
|
agentIsLoading: "Ο πράκτορας φορτώνει...",
|
|
56582
56726
|
conversationResolved: "Η συζήτηση ολοκληρώθηκε",
|
|
@@ -56609,6 +56753,12 @@
|
|
|
56609
56753
|
allowMicAccess: "Επιτρέψτε πρόσβαση στο μικρόφωνο"
|
|
56610
56754
|
},
|
|
56611
56755
|
hi: {
|
|
56756
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56757
|
+
// substituted verbatim at the call site and rendered through
|
|
56758
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56759
|
+
chooseTopicLabel: "शुरू करने के लिए एक विषय चुनें:",
|
|
56760
|
+
categoryTopicsHeading: "कृपया अपना **{category}** प्रश्न नीचे पूछें।",
|
|
56761
|
+
quickQuestionsHeadingLabel: "या एक त्वरित प्रश्न पूछें:",
|
|
56612
56762
|
typeYourMessage: "अपना संदेश लिखें...",
|
|
56613
56763
|
agentIsLoading: "एजेंट लोड हो रहा है...",
|
|
56614
56764
|
conversationResolved: "बातचीत समाप्त हुई",
|
|
@@ -56643,6 +56793,12 @@
|
|
|
56643
56793
|
allowMicAccess: "माइक्रोफ़ोन एक्सेस की अनुमति दें"
|
|
56644
56794
|
},
|
|
56645
56795
|
mr: {
|
|
56796
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56797
|
+
// substituted verbatim at the call site and rendered through
|
|
56798
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56799
|
+
chooseTopicLabel: "सुरू करण्यासाठी एक विषय निवडा:",
|
|
56800
|
+
categoryTopicsHeading: "कृपया तुमचा **{category}** प्रश्न खाली विचारा.",
|
|
56801
|
+
quickQuestionsHeadingLabel: "किंवा एक झटपट प्रश्न विचारा:",
|
|
56646
56802
|
typeYourMessage: "तुमचा संदेश टाइप करा...",
|
|
56647
56803
|
agentIsLoading: "एजंट लोड होत आहे...",
|
|
56648
56804
|
conversationResolved: "संभाषण समाप्त",
|
|
@@ -56677,6 +56833,12 @@
|
|
|
56677
56833
|
allowMicAccess: "मायक्रोफोन प्रवेशास परवानगी द्या"
|
|
56678
56834
|
},
|
|
56679
56835
|
hu: {
|
|
56836
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56837
|
+
// substituted verbatim at the call site and rendered through
|
|
56838
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56839
|
+
chooseTopicLabel: "Válassz egy témát a kezdéshez:",
|
|
56840
|
+
categoryTopicsHeading: "Kérjük, tedd fel **{category}** kérdésedet alább.",
|
|
56841
|
+
quickQuestionsHeadingLabel: "Vagy tegyél fel egy gyors kérdést:",
|
|
56680
56842
|
typeYourMessage: "Írja be az üzenetét...",
|
|
56681
56843
|
agentIsLoading: "Az ügynök betöltődik...",
|
|
56682
56844
|
conversationResolved: "Beszélgetés befejezve",
|
|
@@ -56709,6 +56871,12 @@
|
|
|
56709
56871
|
allowMicAccess: "Mikrofon hozzáférés engedélyezése"
|
|
56710
56872
|
},
|
|
56711
56873
|
is: {
|
|
56874
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56875
|
+
// substituted verbatim at the call site and rendered through
|
|
56876
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56877
|
+
chooseTopicLabel: "Veldu efni til að byrja:",
|
|
56878
|
+
categoryTopicsHeading: "Vinsamlegast spurðu spurningu þinnar um **{category}** hér að neðan.",
|
|
56879
|
+
quickQuestionsHeadingLabel: "Eða spurðu fljótlegrar spurningar:",
|
|
56712
56880
|
typeYourMessage: "Sláðu inn skilaboð...",
|
|
56713
56881
|
agentIsLoading: "Fulltrúi hleðst...",
|
|
56714
56882
|
conversationResolved: "Samtali lokið",
|
|
@@ -56741,6 +56909,12 @@
|
|
|
56741
56909
|
allowMicAccess: "Leyfa aðgang að hljóðnema"
|
|
56742
56910
|
},
|
|
56743
56911
|
id: {
|
|
56912
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56913
|
+
// substituted verbatim at the call site and rendered through
|
|
56914
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56915
|
+
chooseTopicLabel: "Pilih topik untuk memulai:",
|
|
56916
|
+
categoryTopicsHeading: "Silakan ajukan pertanyaan **{category}** Anda di bawah.",
|
|
56917
|
+
quickQuestionsHeadingLabel: "Atau ajukan pertanyaan cepat:",
|
|
56744
56918
|
typeYourMessage: "Ketik pesan Anda...",
|
|
56745
56919
|
agentIsLoading: "Agen sedang dimuat...",
|
|
56746
56920
|
conversationResolved: "Percakapan selesai",
|
|
@@ -56773,6 +56947,12 @@
|
|
|
56773
56947
|
allowMicAccess: "Izinkan akses mikrofon"
|
|
56774
56948
|
},
|
|
56775
56949
|
it: {
|
|
56950
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56951
|
+
// substituted verbatim at the call site and rendered through
|
|
56952
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56953
|
+
chooseTopicLabel: "Scegli un argomento per iniziare:",
|
|
56954
|
+
categoryTopicsHeading: "Per favore, poni la tua domanda su **{category}** qui sotto.",
|
|
56955
|
+
quickQuestionsHeadingLabel: "Oppure fai una domanda rapida:",
|
|
56776
56956
|
typeYourMessage: "Scrivi il tuo messaggio...",
|
|
56777
56957
|
agentIsLoading: "L'agente sta caricando...",
|
|
56778
56958
|
conversationResolved: "Conversazione conclusa",
|
|
@@ -56805,6 +56985,12 @@
|
|
|
56805
56985
|
allowMicAccess: "Consenti l'accesso al microfono"
|
|
56806
56986
|
},
|
|
56807
56987
|
ja: {
|
|
56988
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
56989
|
+
// substituted verbatim at the call site and rendered through
|
|
56990
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
56991
|
+
chooseTopicLabel: "始めるにはトピックを選択してください:",
|
|
56992
|
+
categoryTopicsHeading: "**{category}** に関するご質問を以下にお書きください。",
|
|
56993
|
+
quickQuestionsHeadingLabel: "または、簡単な質問をどうぞ:",
|
|
56808
56994
|
typeYourMessage: "メッセージを入力してください...",
|
|
56809
56995
|
agentIsLoading: "エージェントを読み込んでいます...",
|
|
56810
56996
|
conversationResolved: "会話が終了しました",
|
|
@@ -56837,6 +57023,12 @@
|
|
|
56837
57023
|
allowMicAccess: "マイクへのアクセスを許可"
|
|
56838
57024
|
},
|
|
56839
57025
|
ko: {
|
|
57026
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57027
|
+
// substituted verbatim at the call site and rendered through
|
|
57028
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57029
|
+
chooseTopicLabel: "시작하려면 주제를 선택하세요:",
|
|
57030
|
+
categoryTopicsHeading: "**{category}** 에 대한 질문을 아래에 작성해 주세요.",
|
|
57031
|
+
quickQuestionsHeadingLabel: "또는 간단한 질문을 해보세요:",
|
|
56840
57032
|
typeYourMessage: "메시지를 입력하세요...",
|
|
56841
57033
|
agentIsLoading: "상담원을 불러오는 중...",
|
|
56842
57034
|
conversationResolved: "대화가 종료되었습니다",
|
|
@@ -56869,6 +57061,12 @@
|
|
|
56869
57061
|
allowMicAccess: "마이크 액세스 허용"
|
|
56870
57062
|
},
|
|
56871
57063
|
lv: {
|
|
57064
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57065
|
+
// substituted verbatim at the call site and rendered through
|
|
57066
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57067
|
+
chooseTopicLabel: "Izvēlieties tēmu, lai sāktu:",
|
|
57068
|
+
categoryTopicsHeading: "Lūdzu, uzdodiet savu jautājumu par **{category}** zemāk.",
|
|
57069
|
+
quickQuestionsHeadingLabel: "Vai uzdodiet ātru jautājumu:",
|
|
56872
57070
|
typeYourMessage: "Ierakstiet savu ziņu...",
|
|
56873
57071
|
agentIsLoading: "Aģents tiek ielādēts...",
|
|
56874
57072
|
conversationResolved: "Saruna pabeigta",
|
|
@@ -56901,6 +57099,12 @@
|
|
|
56901
57099
|
allowMicAccess: "Atļaut piekļuvi mikrofonam"
|
|
56902
57100
|
},
|
|
56903
57101
|
lt: {
|
|
57102
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57103
|
+
// substituted verbatim at the call site and rendered through
|
|
57104
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57105
|
+
chooseTopicLabel: "Pasirinkite temą, kad pradėtumėte:",
|
|
57106
|
+
categoryTopicsHeading: "Prašome užduoti savo klausimą apie **{category}** žemiau.",
|
|
57107
|
+
quickQuestionsHeadingLabel: "Arba užduokite greitą klausimą:",
|
|
56904
57108
|
typeYourMessage: "Įveskite pranešimą...",
|
|
56905
57109
|
agentIsLoading: "Agentas kraunamas...",
|
|
56906
57110
|
conversationResolved: "Pokalbis baigtas",
|
|
@@ -56933,6 +57137,12 @@
|
|
|
56933
57137
|
allowMicAccess: "Leisti prieigą prie mikrofono"
|
|
56934
57138
|
},
|
|
56935
57139
|
mk: {
|
|
57140
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57141
|
+
// substituted verbatim at the call site and rendered through
|
|
57142
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57143
|
+
chooseTopicLabel: "Изберете тема за да започнете:",
|
|
57144
|
+
categoryTopicsHeading: "Ве молиме поставете го вашето прашање за **{category}** подолу.",
|
|
57145
|
+
quickQuestionsHeadingLabel: "Или поставете брзо прашање:",
|
|
56936
57146
|
typeYourMessage: "Напишете ја вашата порака...",
|
|
56937
57147
|
agentIsLoading: "Агентот се вчитува...",
|
|
56938
57148
|
conversationResolved: "Разговорот е завршен",
|
|
@@ -56965,6 +57175,12 @@
|
|
|
56965
57175
|
allowMicAccess: "Дозволи пристап до микрофонот"
|
|
56966
57176
|
},
|
|
56967
57177
|
ms: {
|
|
57178
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57179
|
+
// substituted verbatim at the call site and rendered through
|
|
57180
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57181
|
+
chooseTopicLabel: "Pilih topik untuk memulakan:",
|
|
57182
|
+
categoryTopicsHeading: "Sila ajukan soalan **{category}** anda di bawah.",
|
|
57183
|
+
quickQuestionsHeadingLabel: "Atau ajukan soalan ringkas:",
|
|
56968
57184
|
typeYourMessage: "Taip mesej anda...",
|
|
56969
57185
|
agentIsLoading: "Ejen sedang dimuatkan...",
|
|
56970
57186
|
conversationResolved: "Perbualan selesai",
|
|
@@ -56997,6 +57213,12 @@
|
|
|
56997
57213
|
allowMicAccess: "Benarkan akses mikrofon"
|
|
56998
57214
|
},
|
|
56999
57215
|
no: {
|
|
57216
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57217
|
+
// substituted verbatim at the call site and rendered through
|
|
57218
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57219
|
+
chooseTopicLabel: "Velg et emne for å komme i gang:",
|
|
57220
|
+
categoryTopicsHeading: "Vennligst still spørsmålet ditt om **{category}** nedenfor.",
|
|
57221
|
+
quickQuestionsHeadingLabel: "Eller still et raskt spørsmål:",
|
|
57000
57222
|
typeYourMessage: "Skriv meldingen din...",
|
|
57001
57223
|
agentIsLoading: "Agenten laster...",
|
|
57002
57224
|
conversationResolved: "Samtale avsluttet",
|
|
@@ -57029,6 +57251,12 @@
|
|
|
57029
57251
|
allowMicAccess: "Tillat mikrofontilgang"
|
|
57030
57252
|
},
|
|
57031
57253
|
fa: {
|
|
57254
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57255
|
+
// substituted verbatim at the call site and rendered through
|
|
57256
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57257
|
+
chooseTopicLabel: "برای شروع، یک موضوع را انتخاب کنید:",
|
|
57258
|
+
categoryTopicsHeading: "لطفاً سؤال خود درباره **{category}** را در زیر مطرح کنید.",
|
|
57259
|
+
quickQuestionsHeadingLabel: "یا یک سؤال سریع بپرسید:",
|
|
57032
57260
|
typeYourMessage: "پیام خود را تایپ کنید...",
|
|
57033
57261
|
agentIsLoading: "در حال بارگذاری نماینده...",
|
|
57034
57262
|
conversationResolved: "مکالمه به پایان رسید",
|
|
@@ -57061,6 +57289,12 @@
|
|
|
57061
57289
|
allowMicAccess: "اجازه دسترسی به میکروفون"
|
|
57062
57290
|
},
|
|
57063
57291
|
pl: {
|
|
57292
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57293
|
+
// substituted verbatim at the call site and rendered through
|
|
57294
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57295
|
+
chooseTopicLabel: "Wybierz temat, aby rozpocząć:",
|
|
57296
|
+
categoryTopicsHeading: "Proszę zadać pytanie dotyczące **{category}** poniżej.",
|
|
57297
|
+
quickQuestionsHeadingLabel: "Lub zadaj szybkie pytanie:",
|
|
57064
57298
|
typeYourMessage: "Wpisz wiadomość...",
|
|
57065
57299
|
agentIsLoading: "Agent się ładuje...",
|
|
57066
57300
|
conversationResolved: "Rozmowa zakończona",
|
|
@@ -57093,6 +57327,12 @@
|
|
|
57093
57327
|
allowMicAccess: "Zezwól na dostęp do mikrofonu"
|
|
57094
57328
|
},
|
|
57095
57329
|
pt: {
|
|
57330
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57331
|
+
// substituted verbatim at the call site and rendered through
|
|
57332
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57333
|
+
chooseTopicLabel: "Escolha um tópico para começar:",
|
|
57334
|
+
categoryTopicsHeading: "Por favor, faça sua pergunta sobre **{category}** abaixo.",
|
|
57335
|
+
quickQuestionsHeadingLabel: "Ou faça uma pergunta rápida:",
|
|
57096
57336
|
typeYourMessage: "Digite sua mensagem...",
|
|
57097
57337
|
agentIsLoading: "O agente está carregando...",
|
|
57098
57338
|
conversationResolved: "Conversa encerrada",
|
|
@@ -57125,6 +57365,12 @@
|
|
|
57125
57365
|
allowMicAccess: "Permitir acesso ao microfone"
|
|
57126
57366
|
},
|
|
57127
57367
|
ro: {
|
|
57368
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57369
|
+
// substituted verbatim at the call site and rendered through
|
|
57370
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57371
|
+
chooseTopicLabel: "Alegeți un subiect pentru a începe:",
|
|
57372
|
+
categoryTopicsHeading: "Vă rugăm să adresați întrebarea dvs. despre **{category}** mai jos.",
|
|
57373
|
+
quickQuestionsHeadingLabel: "Sau puneți o întrebare rapidă:",
|
|
57128
57374
|
typeYourMessage: "Scrieți mesajul dvs...",
|
|
57129
57375
|
agentIsLoading: "Agentul se încarcă...",
|
|
57130
57376
|
conversationResolved: "Conversație încheiată",
|
|
@@ -57157,6 +57403,12 @@
|
|
|
57157
57403
|
allowMicAccess: "Permiteți accesul la microfon"
|
|
57158
57404
|
},
|
|
57159
57405
|
ru: {
|
|
57406
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57407
|
+
// substituted verbatim at the call site and rendered through
|
|
57408
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57409
|
+
chooseTopicLabel: "Выберите тему, чтобы начать:",
|
|
57410
|
+
categoryTopicsHeading: "Пожалуйста, задайте свой вопрос о **{category}** ниже.",
|
|
57411
|
+
quickQuestionsHeadingLabel: "Или задайте быстрый вопрос:",
|
|
57160
57412
|
typeYourMessage: "Введите ваше сообщение...",
|
|
57161
57413
|
agentIsLoading: "Агент загружается...",
|
|
57162
57414
|
conversationResolved: "Разговор завершен",
|
|
@@ -57189,6 +57441,12 @@
|
|
|
57189
57441
|
allowMicAccess: "Разрешить доступ к микрофону"
|
|
57190
57442
|
},
|
|
57191
57443
|
sr: {
|
|
57444
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57445
|
+
// substituted verbatim at the call site and rendered through
|
|
57446
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57447
|
+
chooseTopicLabel: "Изаберите тему да бисте започели:",
|
|
57448
|
+
categoryTopicsHeading: "Молимо поставите своје питање о **{category}** испод.",
|
|
57449
|
+
quickQuestionsHeadingLabel: "Или поставите брзо питање:",
|
|
57192
57450
|
typeYourMessage: "Укуцајте вашу поруку...",
|
|
57193
57451
|
agentIsLoading: "Агент се учитава...",
|
|
57194
57452
|
conversationResolved: "Разговор је завршен",
|
|
@@ -57221,6 +57479,12 @@
|
|
|
57221
57479
|
allowMicAccess: "Дозволи приступ микрофону"
|
|
57222
57480
|
},
|
|
57223
57481
|
sk: {
|
|
57482
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57483
|
+
// substituted verbatim at the call site and rendered through
|
|
57484
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57485
|
+
chooseTopicLabel: "Vyberte tému, aby ste začali:",
|
|
57486
|
+
categoryTopicsHeading: "Prosím, položte svoju otázku o **{category}** nižšie.",
|
|
57487
|
+
quickQuestionsHeadingLabel: "Alebo položte rýchlu otázku:",
|
|
57224
57488
|
typeYourMessage: "Napíšte svoju správu...",
|
|
57225
57489
|
agentIsLoading: "Agent sa načítava...",
|
|
57226
57490
|
conversationResolved: "Konverzácia ukončená",
|
|
@@ -57253,6 +57517,12 @@
|
|
|
57253
57517
|
allowMicAccess: "Povoliť prístup k mikrofónu"
|
|
57254
57518
|
},
|
|
57255
57519
|
sl: {
|
|
57520
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57521
|
+
// substituted verbatim at the call site and rendered through
|
|
57522
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57523
|
+
chooseTopicLabel: "Izberite temo za začetek:",
|
|
57524
|
+
categoryTopicsHeading: "Prosimo, postavite vprašanje o **{category}** spodaj.",
|
|
57525
|
+
quickQuestionsHeadingLabel: "Ali postavite hitro vprašanje:",
|
|
57256
57526
|
typeYourMessage: "Vnesite svoje sporočilo...",
|
|
57257
57527
|
agentIsLoading: "Agent se nalaga...",
|
|
57258
57528
|
conversationResolved: "Pogovor je končan",
|
|
@@ -57285,6 +57555,12 @@
|
|
|
57285
57555
|
allowMicAccess: "Dovoli dostop do mikrofona"
|
|
57286
57556
|
},
|
|
57287
57557
|
sv: {
|
|
57558
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57559
|
+
// substituted verbatim at the call site and rendered through
|
|
57560
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57561
|
+
chooseTopicLabel: "Välj ett ämne för att komma igång:",
|
|
57562
|
+
categoryTopicsHeading: "Ställ gärna din **{category}**-fråga nedan.",
|
|
57563
|
+
quickQuestionsHeadingLabel: "Eller ställ en snabb fråga:",
|
|
57288
57564
|
typeYourMessage: "Skriv ditt meddelande...",
|
|
57289
57565
|
agentIsLoading: "Agenten laddas...",
|
|
57290
57566
|
conversationResolved: "Konversation avslutad",
|
|
@@ -57317,6 +57593,12 @@
|
|
|
57317
57593
|
allowMicAccess: "Tillåt mikrofonåtkomst"
|
|
57318
57594
|
},
|
|
57319
57595
|
th: {
|
|
57596
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57597
|
+
// substituted verbatim at the call site and rendered through
|
|
57598
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57599
|
+
chooseTopicLabel: "เลือกหัวข้อเพื่อเริ่มต้น:",
|
|
57600
|
+
categoryTopicsHeading: "โปรดถามคำถามเกี่ยวกับ **{category}** ด้านล่าง",
|
|
57601
|
+
quickQuestionsHeadingLabel: "หรือถามคำถามด่วน:",
|
|
57320
57602
|
typeYourMessage: "พิมพ์ข้อความของคุณ...",
|
|
57321
57603
|
agentIsLoading: "กำลังโหลดตัวแทน...",
|
|
57322
57604
|
conversationResolved: "การสนทนาสิ้นสุดลง",
|
|
@@ -57349,6 +57631,12 @@
|
|
|
57349
57631
|
allowMicAccess: "อนุญาตการเข้าถึงไมโครโฟน"
|
|
57350
57632
|
},
|
|
57351
57633
|
tr: {
|
|
57634
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57635
|
+
// substituted verbatim at the call site and rendered through
|
|
57636
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57637
|
+
chooseTopicLabel: "Başlamak için bir konu seçin:",
|
|
57638
|
+
categoryTopicsHeading: "Lütfen **{category}** sorunuzu aşağıya yazın.",
|
|
57639
|
+
quickQuestionsHeadingLabel: "Veya hızlı bir soru sorun:",
|
|
57352
57640
|
typeYourMessage: "Mesajınızı yazın...",
|
|
57353
57641
|
agentIsLoading: "Temsilci yükleniyor...",
|
|
57354
57642
|
conversationResolved: "Görüşme sonlandırıldı",
|
|
@@ -57381,6 +57669,12 @@
|
|
|
57381
57669
|
allowMicAccess: "Mikrofon erişimine izin ver"
|
|
57382
57670
|
},
|
|
57383
57671
|
uk: {
|
|
57672
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57673
|
+
// substituted verbatim at the call site and rendered through
|
|
57674
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57675
|
+
chooseTopicLabel: "Виберіть тему, щоб почати:",
|
|
57676
|
+
categoryTopicsHeading: "Будь ласка, поставте своє запитання щодо **{category}** нижче.",
|
|
57677
|
+
quickQuestionsHeadingLabel: "Або поставте швидке запитання:",
|
|
57384
57678
|
typeYourMessage: "Введіть ваше повідомлення...",
|
|
57385
57679
|
agentIsLoading: "Агент завантажується...",
|
|
57386
57680
|
conversationResolved: "Розмову завершено",
|
|
@@ -57413,6 +57707,12 @@
|
|
|
57413
57707
|
allowMicAccess: "Дозволити доступ до мікрофона"
|
|
57414
57708
|
},
|
|
57415
57709
|
ur: {
|
|
57710
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57711
|
+
// substituted verbatim at the call site and rendered through
|
|
57712
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57713
|
+
chooseTopicLabel: "شروع کرنے کے لیے ایک موضوع منتخب کریں:",
|
|
57714
|
+
categoryTopicsHeading: "براہ کرم اپنا **{category}** سوال نیچے پوچھیں۔",
|
|
57715
|
+
quickQuestionsHeadingLabel: "یا کوئی فوری سوال پوچھیں:",
|
|
57416
57716
|
typeYourMessage: "اپنا پیغام ٹائپ کریں...",
|
|
57417
57717
|
agentIsLoading: "ایجنٹ لوڈ ہو رہا ہے...",
|
|
57418
57718
|
conversationResolved: "گفتگو مکمل",
|
|
@@ -57445,6 +57745,12 @@
|
|
|
57445
57745
|
allowMicAccess: "مائیکروفون تک رسائی کی اجازت دیں"
|
|
57446
57746
|
},
|
|
57447
57747
|
vi: {
|
|
57748
|
+
// Topic-picker + quick-questions surface strings. {category} is
|
|
57749
|
+
// substituted verbatim at the call site and rendered through
|
|
57750
|
+
// ReactMarkdown — keep the **{category}** bold wrapper.
|
|
57751
|
+
chooseTopicLabel: "Chọn một chủ đề để bắt đầu:",
|
|
57752
|
+
categoryTopicsHeading: "Vui lòng đặt câu hỏi của bạn về **{category}** bên dưới.",
|
|
57753
|
+
quickQuestionsHeadingLabel: "Hoặc đặt một câu hỏi nhanh:",
|
|
57448
57754
|
typeYourMessage: "Nhập tin nhắn của bạn...",
|
|
57449
57755
|
agentIsLoading: "Đang tải trợ lý...",
|
|
57450
57756
|
conversationResolved: "Cuộc trò chuyện đã kết thúc",
|
|
@@ -60013,6 +60319,64 @@
|
|
|
60013
60319
|
});
|
|
60014
60320
|
};
|
|
60015
60321
|
|
|
60322
|
+
const createSession = async config => {
|
|
60323
|
+
// Initialize chat session if needed
|
|
60324
|
+
if (config.sessionUrl) {
|
|
60325
|
+
try {
|
|
60326
|
+
const response = await fetch(config.sessionUrl, {
|
|
60327
|
+
method: "POST",
|
|
60328
|
+
headers: _objectSpread2({
|
|
60329
|
+
"Content-Type": "application/json"
|
|
60330
|
+
}, config.apiKey && {
|
|
60331
|
+
Authorization: "Bearer ".concat(config.apiKey)
|
|
60332
|
+
}),
|
|
60333
|
+
body: JSON.stringify({
|
|
60334
|
+
userId: config.userId,
|
|
60335
|
+
userName: config.userName,
|
|
60336
|
+
userEmail: config.userEmail
|
|
60337
|
+
}),
|
|
60338
|
+
credentials: "include"
|
|
60339
|
+
});
|
|
60340
|
+
const data = await response.json();
|
|
60341
|
+
return data.sessionId;
|
|
60342
|
+
} catch (error) {
|
|
60343
|
+
console.error("Session creation error:", error);
|
|
60344
|
+
return null;
|
|
60345
|
+
}
|
|
60346
|
+
}
|
|
60347
|
+
return null;
|
|
60348
|
+
};
|
|
60349
|
+
|
|
60350
|
+
/**
|
|
60351
|
+
* Fetches agent configuration from the deploy-agent endpoint
|
|
60352
|
+
* @param {string} apiBaseUrl - Base URL for the API
|
|
60353
|
+
* @param {string} orgId - Organization ID
|
|
60354
|
+
* @returns {Promise<object>} Agent configuration object
|
|
60355
|
+
*/
|
|
60356
|
+
const fetchAgentConfig = async (apiBaseUrl, orgId) => {
|
|
60357
|
+
if (!apiBaseUrl || !orgId) {
|
|
60358
|
+
throw new Error("apiBaseUrl and orgId are required");
|
|
60359
|
+
}
|
|
60360
|
+
try {
|
|
60361
|
+
const url = "".concat(apiBaseUrl.replace(/\/$/, ''), "/api/v1/deploy-agent/").concat(orgId);
|
|
60362
|
+
const response = await fetch(url, {
|
|
60363
|
+
method: "GET",
|
|
60364
|
+
headers: {
|
|
60365
|
+
"Content-Type": "application/json"
|
|
60366
|
+
},
|
|
60367
|
+
credentials: "include"
|
|
60368
|
+
});
|
|
60369
|
+
if (!response.ok) {
|
|
60370
|
+
throw new Error("HTTP error! status: ".concat(response.status));
|
|
60371
|
+
}
|
|
60372
|
+
const data = await response.json();
|
|
60373
|
+
return data;
|
|
60374
|
+
} catch (error) {
|
|
60375
|
+
console.error("Failed to fetch agent configuration:", error);
|
|
60376
|
+
throw error;
|
|
60377
|
+
}
|
|
60378
|
+
};
|
|
60379
|
+
|
|
60016
60380
|
const ChatWidget = _ref => {
|
|
60017
60381
|
var _agentConfig$concierg;
|
|
60018
60382
|
let {
|
|
@@ -60091,7 +60455,7 @@
|
|
|
60091
60455
|
|
|
60092
60456
|
// Map API response to widget props (use props as overrides if provided)
|
|
60093
60457
|
const widgetConfig = reactExports.useMemo(() => {
|
|
60094
|
-
var _agentConfig$config, _cfg$identity, _cfg$branding, _cfg$typography, _cfg$messages, _cfg$voice, _cfg$onboarding, _cfg$disclaimer, _cfg$csat, _cfg$inactivity, _cfg$behavior, _cfg$security, _cfg$layout, _ref2,
|
|
60458
|
+
var _agentConfig$config, _cfg$identity, _cfg$branding, _cfg$typography, _cfg$messages, _cfg$voice, _cfg$onboarding, _cfg$disclaimer, _cfg$csat, _cfg$inactivity, _cfg$behavior, _cfg$security, _cfg$layout, _ref2, _messages$bundles$loc, _messages$bundles, _messages$bundles$en, _messages$bundles2, _ref3, _ref4, _ref5, _ref6, _branding$chatbotAvat, _branding$chatbotAvat2, _ref7, _ref8, _ref9, _ref0, _ref1, _ref10, _ref11, _ref12, _ref13, _ref14, _ref15, _ref16, _ref17, _ref18, _inactivity$timeoutVa, _inactivity$timeoutUn, _ref19, _ref20, _ref21, _ref22, _ref23, _ref24, _ref25, _ref26, _csat$enabled, _csat$format, _csat$prompt, _csat$triggerType, _csat$idleTimeoutMins, _csat$followUpEnabled, _csat$followUpPrompt, _behavior$autoPromptE, _behavior$allowFeedba;
|
|
60095
60459
|
if (!agentConfig) {
|
|
60096
60460
|
return null;
|
|
60097
60461
|
}
|
|
@@ -60111,55 +60475,69 @@
|
|
|
60111
60475
|
const security = (_cfg$security = cfg.security) !== null && _cfg$security !== void 0 ? _cfg$security : {};
|
|
60112
60476
|
const layout = (_cfg$layout = cfg.layout) !== null && _cfg$layout !== void 0 ? _cfg$layout : {};
|
|
60113
60477
|
const locale = (_ref2 = defaultLanguage !== null && defaultLanguage !== void 0 ? defaultLanguage : messages.defaultLocale) !== null && _ref2 !== void 0 ? _ref2 : "en";
|
|
60114
|
-
|
|
60478
|
+
// Per-field English fallback for the localized bundle. We can't use
|
|
60479
|
+
// `bundles[locale] ?? bundles.en` because `??` only catches
|
|
60480
|
+
// null/undefined — and the Languages config UI doesn't currently
|
|
60481
|
+
// expose per-language welcome / quickQuestions text, so picking
|
|
60482
|
+
// Hindi (etc.) as default leaves `bundles.hi = { welcome: "",
|
|
60483
|
+
// quickQuestions: [] }`. The empty string would shadow English and
|
|
60484
|
+
// useChatState (`if (!welcomeMessage) return []`) silently skips
|
|
60485
|
+
// the greeting bubble. Treat empty string / empty array as
|
|
60486
|
+
// "missing" and fall back to the English bundle for that field.
|
|
60487
|
+
const localeBundle = (_messages$bundles$loc = (_messages$bundles = messages.bundles) === null || _messages$bundles === void 0 ? void 0 : _messages$bundles[locale]) !== null && _messages$bundles$loc !== void 0 ? _messages$bundles$loc : {};
|
|
60488
|
+
const enBundle = (_messages$bundles$en = (_messages$bundles2 = messages.bundles) === null || _messages$bundles2 === void 0 ? void 0 : _messages$bundles2["en"]) !== null && _messages$bundles$en !== void 0 ? _messages$bundles$en : {};
|
|
60489
|
+
const bundle = {
|
|
60490
|
+
welcome: localeBundle.welcome || enBundle.welcome,
|
|
60491
|
+
quickQuestions: Array.isArray(localeBundle.quickQuestions) && localeBundle.quickQuestions.length > 0 ? localeBundle.quickQuestions : enBundle.quickQuestions
|
|
60492
|
+
};
|
|
60115
60493
|
|
|
60116
60494
|
// Enum values from the DB are UPPER_SNAKE_CASE; widget uses lower-kebab-case
|
|
60117
60495
|
const toLauncherPos = val => val ? val.toLowerCase().replace(/_/g, "-") : "bottom-right";
|
|
60118
60496
|
const toDisclaimerPos = val => val ? val.toLowerCase() : "top";
|
|
60119
|
-
const finalAllowedDomains = (
|
|
60497
|
+
const finalAllowedDomains = (_ref3 = allowedDomains !== null && allowedDomains !== void 0 ? allowedDomains : security.allowedDomains) !== null && _ref3 !== void 0 ? _ref3 : [];
|
|
60120
60498
|
return {
|
|
60121
60499
|
darkMode: darkMode !== null && darkMode !== void 0 ? darkMode : false,
|
|
60122
|
-
primaryColor: (
|
|
60123
|
-
companyName: (
|
|
60500
|
+
primaryColor: (_ref4 = primaryColor !== null && primaryColor !== void 0 ? primaryColor : branding.brandColor) !== null && _ref4 !== void 0 ? _ref4 : "#2563eb",
|
|
60501
|
+
companyName: (_ref5 = companyName !== null && companyName !== void 0 ? companyName : identity.companyName) !== null && _ref5 !== void 0 ? _ref5 : "Support Team",
|
|
60124
60502
|
conciergeName: conciergeName !== null && conciergeName !== void 0 ? conciergeName : identity.conciergeName,
|
|
60125
|
-
companyLogo: (
|
|
60503
|
+
companyLogo: (_ref6 = companyLogo !== null && companyLogo !== void 0 ? companyLogo : branding.avatar) !== null && _ref6 !== void 0 ? _ref6 : null,
|
|
60126
60504
|
chatbotAvatarEnabled: (_branding$chatbotAvat = branding.chatbotAvatarEnabled) !== null && _branding$chatbotAvat !== void 0 ? _branding$chatbotAvat : false,
|
|
60127
60505
|
chatbotAvatar: (_branding$chatbotAvat2 = branding.chatbotAvatar) !== null && _branding$chatbotAvat2 !== void 0 ? _branding$chatbotAvat2 : null,
|
|
60128
|
-
welcomeMessage: (
|
|
60129
|
-
quickQuestions: (
|
|
60506
|
+
welcomeMessage: (_ref7 = welcomeMessage !== null && welcomeMessage !== void 0 ? welcomeMessage : bundle.welcome) !== null && _ref7 !== void 0 ? _ref7 : "Hi! How can we help?",
|
|
60507
|
+
quickQuestions: (_ref8 = quickQuestions !== null && quickQuestions !== void 0 ? quickQuestions : bundle.quickQuestions) !== null && _ref8 !== void 0 ? _ref8 : [],
|
|
60130
60508
|
quickQuestionsEnabled: quickQuestionsEnabled !== null && quickQuestionsEnabled !== void 0 ? quickQuestionsEnabled : messages.quickQuestionsEnabled,
|
|
60131
60509
|
textColor: textColor !== null && textColor !== void 0 ? textColor : "#000000",
|
|
60132
60510
|
agentMessageBubbleColor: agentMessageBubbleColor !== null && agentMessageBubbleColor !== void 0 ? agentMessageBubbleColor : typography.agentMessageBubbleColor,
|
|
60133
60511
|
userMessageBoxColor: userMessageBoxColor !== null && userMessageBoxColor !== void 0 ? userMessageBoxColor : typography.userMessageBoxColor,
|
|
60134
|
-
assistantTextColor: (
|
|
60135
|
-
userTextColor: (
|
|
60136
|
-
fontFamily: (
|
|
60137
|
-
fontSize: (
|
|
60512
|
+
assistantTextColor: (_ref9 = assistantTextColor !== null && assistantTextColor !== void 0 ? assistantTextColor : typography.assistantTextColor) !== null && _ref9 !== void 0 ? _ref9 : "#000000",
|
|
60513
|
+
userTextColor: (_ref0 = userTextColor !== null && userTextColor !== void 0 ? userTextColor : typography.userTextColor) !== null && _ref0 !== void 0 ? _ref0 : "#000000",
|
|
60514
|
+
fontFamily: (_ref1 = fontFamily !== null && fontFamily !== void 0 ? fontFamily : typography.agentMessageBubbleFontFamily) !== null && _ref1 !== void 0 ? _ref1 : "Inter",
|
|
60515
|
+
fontSize: (_ref10 = fontSize !== null && fontSize !== void 0 ? fontSize : typography.agentMessageBubbleFontSize) !== null && _ref10 !== void 0 ? _ref10 : "14px",
|
|
60138
60516
|
defaultLanguage: locale,
|
|
60139
60517
|
organizationId: orgId,
|
|
60140
|
-
headerTextBold: (
|
|
60141
|
-
headerTextItalic: (
|
|
60518
|
+
headerTextBold: (_ref11 = headerTextBold !== null && headerTextBold !== void 0 ? headerTextBold : typography.headerTextBold) !== null && _ref11 !== void 0 ? _ref11 : false,
|
|
60519
|
+
headerTextItalic: (_ref12 = headerTextItalic !== null && headerTextItalic !== void 0 ? headerTextItalic : typography.headerTextItalic) !== null && _ref12 !== void 0 ? _ref12 : false,
|
|
60142
60520
|
headerTextColor: typography.headerTextColor,
|
|
60143
60521
|
headerFontFamily: typography.headerFontFamily,
|
|
60144
60522
|
headerFontSize: typography.headerFontSize,
|
|
60145
|
-
enableVoiceInteraction: (
|
|
60146
|
-
disclaimerEnabled: (
|
|
60523
|
+
enableVoiceInteraction: (_ref13 = enableVoiceInteraction !== null && enableVoiceInteraction !== void 0 ? enableVoiceInteraction : voice.enableVoiceInteraction) !== null && _ref13 !== void 0 ? _ref13 : false,
|
|
60524
|
+
disclaimerEnabled: (_ref14 = disclaimerEnabled !== null && disclaimerEnabled !== void 0 ? disclaimerEnabled : disclaimer.enabled) !== null && _ref14 !== void 0 ? _ref14 : false,
|
|
60147
60525
|
disclaimerText: disclaimerText !== null && disclaimerText !== void 0 ? disclaimerText : disclaimer.text,
|
|
60148
60526
|
disclaimerPosition: disclaimerPosition !== null && disclaimerPosition !== void 0 ? disclaimerPosition : toDisclaimerPos(disclaimer.position),
|
|
60149
60527
|
disclaimerLinkUrl: normalizeExternalUrl(disclaimerLinkUrl !== null && disclaimerLinkUrl !== void 0 ? disclaimerLinkUrl : disclaimer.linkUrl),
|
|
60150
60528
|
disclaimerLinkLabel: disclaimerLinkLabel !== null && disclaimerLinkLabel !== void 0 ? disclaimerLinkLabel : disclaimer.linkLabel,
|
|
60151
|
-
showPoweredBy: (
|
|
60152
|
-
onboardingQuestions: (
|
|
60153
|
-
collectionPrompt: (
|
|
60529
|
+
showPoweredBy: (_ref15 = showPoweredBy !== null && showPoweredBy !== void 0 ? showPoweredBy : branding.showPoweredBy) !== null && _ref15 !== void 0 ? _ref15 : true,
|
|
60530
|
+
onboardingQuestions: (_ref16 = onboardingQuestions !== null && onboardingQuestions !== void 0 ? onboardingQuestions : onboarding.questions) !== null && _ref16 !== void 0 ? _ref16 : [],
|
|
60531
|
+
collectionPrompt: (_ref17 = collectionPrompt !== null && collectionPrompt !== void 0 ? collectionPrompt : onboarding.collapsiblePrompt) !== null && _ref17 !== void 0 ? _ref17 : "Before we begin, I need to verify your details.",
|
|
60154
60532
|
allowedDomains: finalAllowedDomains,
|
|
60155
60533
|
launcherPosition: position !== null && position !== void 0 ? position : toLauncherPos(layout.launcherPosition),
|
|
60156
|
-
onboardingEnabled: (
|
|
60534
|
+
onboardingEnabled: (_ref18 = onboardingEnabled !== null && onboardingEnabled !== void 0 ? onboardingEnabled : onboarding.enabled) !== null && _ref18 !== void 0 ? _ref18 : false,
|
|
60157
60535
|
inactivityTimeoutValue: (_inactivity$timeoutVa = inactivity.timeoutValue) !== null && _inactivity$timeoutVa !== void 0 ? _inactivity$timeoutVa : null,
|
|
60158
60536
|
inactivityTimeoutUnit: (_inactivity$timeoutUn = inactivity.timeoutUnit) !== null && _inactivity$timeoutUn !== void 0 ? _inactivity$timeoutUn : null,
|
|
60159
|
-
agentMessageBubbleFontFamily: (
|
|
60160
|
-
agentMessageBubbleFontSize: (
|
|
60161
|
-
userMessageBubbleFontFamily: (
|
|
60162
|
-
userMessageBubbleFontSize: (
|
|
60537
|
+
agentMessageBubbleFontFamily: (_ref19 = (_ref20 = agentMessageBubbleFontFamily !== null && agentMessageBubbleFontFamily !== void 0 ? agentMessageBubbleFontFamily : typography.agentMessageBubbleFontFamily) !== null && _ref20 !== void 0 ? _ref20 : fontFamily) !== null && _ref19 !== void 0 ? _ref19 : "Inter",
|
|
60538
|
+
agentMessageBubbleFontSize: (_ref21 = (_ref22 = agentMessageBubbleFontSize !== null && agentMessageBubbleFontSize !== void 0 ? agentMessageBubbleFontSize : typography.agentMessageBubbleFontSize) !== null && _ref22 !== void 0 ? _ref22 : fontSize) !== null && _ref21 !== void 0 ? _ref21 : "14px",
|
|
60539
|
+
userMessageBubbleFontFamily: (_ref23 = (_ref24 = userMessageBubbleFontFamily !== null && userMessageBubbleFontFamily !== void 0 ? userMessageBubbleFontFamily : typography.userMessageBubbleFontFamily) !== null && _ref24 !== void 0 ? _ref24 : fontFamily) !== null && _ref23 !== void 0 ? _ref23 : "Inter",
|
|
60540
|
+
userMessageBubbleFontSize: (_ref25 = (_ref26 = userMessageBubbleFontSize !== null && userMessageBubbleFontSize !== void 0 ? userMessageBubbleFontSize : typography.userMessageBubbleFontSize) !== null && _ref26 !== void 0 ? _ref26 : fontSize) !== null && _ref25 !== void 0 ? _ref25 : "14px",
|
|
60163
60541
|
csatEnabled: (_csat$enabled = csat.enabled) !== null && _csat$enabled !== void 0 ? _csat$enabled : false,
|
|
60164
60542
|
csatFormat: (_csat$format = csat.format) !== null && _csat$format !== void 0 ? _csat$format : "EMOJI",
|
|
60165
60543
|
csatPrompt: (_csat$prompt = csat.prompt) !== null && _csat$prompt !== void 0 ? _csat$prompt : "How was your experience?",
|
|
@@ -60250,7 +60628,13 @@
|
|
|
60250
60628
|
onboardingEnabled: widgetConfig.onboardingEnabled,
|
|
60251
60629
|
collectionPrompt: widgetConfig.collectionPrompt,
|
|
60252
60630
|
inactivityTimeoutValue: widgetConfig.inactivityTimeoutValue,
|
|
60253
|
-
inactivityTimeoutUnit: widgetConfig.inactivityTimeoutUnit
|
|
60631
|
+
inactivityTimeoutUnit: widgetConfig.inactivityTimeoutUnit,
|
|
60632
|
+
// Sliding-window cap for the localStorage transcript. Comes from
|
|
60633
|
+
// GET /deploy-agent/:orgId → agentConfig.messageLimits (single
|
|
60634
|
+
// source of truth across surfaces). When the field is missing
|
|
60635
|
+
// (older backend / fetch in flight) the hook falls back to its
|
|
60636
|
+
// module-level defaults so chat never blocks on this.
|
|
60637
|
+
messageLimits: agentConfig === null || agentConfig === void 0 ? void 0 : agentConfig.messageLimits
|
|
60254
60638
|
} : defaultConfig);
|
|
60255
60639
|
|
|
60256
60640
|
// Feedback handler — POST to /api/v1/support/feedback
|