@eshal-bot/chat-widget 0.1.63 → 0.1.64

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.
@@ -8011,18 +8011,14 @@
8011
8011
  * @param {object} request - Chat request object
8012
8012
  * @param {string} apiBaseUrl - Base URL for the API
8013
8013
  */
8014
- const sendStreamingRequest = async (request, apiBaseUrl, organizationId, secretKey) => {
8014
+ const sendStreamingRequest = async (request, apiBaseUrl, organizationId) => {
8015
8015
  const headers = {
8016
8016
  'Content-Type': 'application/json',
8017
8017
  Accept: 'text/event-stream'
8018
8018
  };
8019
8019
 
8020
- // Mode A — secret key (direct embed): key replaces orgId in the header
8021
- // Mode B — proxy (@eshal-bot/server): no header from widget; proxy injects x-eshal-sig + x-eshal-org
8022
- // Mode C — legacy: orgId sent directly
8023
- if (secretKey) {
8024
- headers['x-eshal-key'] = secretKey;
8025
- } else if (organizationId) {
8020
+ // Add organization ID header if provided
8021
+ if (organizationId) {
8026
8022
  headers['x-eshal-org'] = organizationId;
8027
8023
  }
8028
8024
  const response = await fetch("".concat(apiBaseUrl.replace(/\/$/, ''), "/api/v1/support"), {
@@ -9133,7 +9129,6 @@
9133
9129
  apiBaseUrl,
9134
9130
  apiKey,
9135
9131
  organizationId,
9136
- secretKey,
9137
9132
  autoOpen,
9138
9133
  openDelay,
9139
9134
  darkMode,
@@ -9770,7 +9765,7 @@
9770
9765
  if (apiType === 'userName' || apiType === 'email' || apiType === 'phone') {
9771
9766
  // For onboarding fields, just consume the stream without processing.
9772
9767
  // Single attempt — no retry, no user-visible partial state to clean up.
9773
- const stream = await sendStreamingRequest(chatRequest, apiBaseUrl, organizationId, secretKey);
9768
+ const stream = await sendStreamingRequest(chatRequest, apiBaseUrl, organizationId);
9774
9769
  const reader = stream.getReader();
9775
9770
  const decoder = new TextDecoder();
9776
9771
  while (true) {
@@ -9789,7 +9784,7 @@
9789
9784
  let lastErr;
9790
9785
  for (let attempt = 0; attempt <= STREAM_RETRY_DELAYS_MS.length; attempt += 1) {
9791
9786
  try {
9792
- const stream = await sendStreamingRequest(chatRequest, apiBaseUrl, organizationId, secretKey);
9787
+ const stream = await sendStreamingRequest(chatRequest, apiBaseUrl, organizationId);
9793
9788
  await processStream(stream, setMessages);
9794
9789
  updateActivity(organizationId);
9795
9790
  return {
@@ -99633,7 +99628,6 @@
99633
99628
  apiBaseUrl,
99634
99629
  apiKey,
99635
99630
  organizationId,
99636
- secretKey,
99637
99631
  conversationId,
99638
99632
  conciergeId,
99639
99633
  onboardingQuestions = [],
@@ -100430,7 +100424,6 @@
100430
100424
  /**
100431
100425
  * @param {string|undefined|null} apiBaseUrl
100432
100426
  * @param {string|undefined|null} orgId
100433
- * @param {string|undefined|null} secretKey — Mode A/B: orgId resolved server-side
100434
100427
  * @returns {{
100435
100428
  * categories: Array<{id:string,label:string,count:number,tags:string[]}>,
100436
100429
  * loading: boolean,
@@ -100438,17 +100431,14 @@
100438
100431
  * hasFilters: boolean,
100439
100432
  * }}
100440
100433
  */
100441
- function useFilterCatalog(apiBaseUrl, orgId, secretKey) {
100442
- // Mode A: secretKey present, orgId null → key-based endpoint
100443
- // Mode C: orgId present (legacy) → orgId-in-path endpoint
100444
- const hasAuth = !!(apiBaseUrl && (orgId || secretKey));
100434
+ function useFilterCatalog(apiBaseUrl, orgId) {
100445
100435
  const [state, setState] = reactExports.useState({
100446
100436
  categories: [],
100447
- loading: hasAuth,
100437
+ loading: !!(apiBaseUrl && orgId),
100448
100438
  error: null
100449
100439
  });
100450
100440
  reactExports.useEffect(() => {
100451
- if (!apiBaseUrl || !orgId && !secretKey) {
100441
+ if (!apiBaseUrl || !orgId) {
100452
100442
  setState({
100453
100443
  categories: [],
100454
100444
  loading: false,
@@ -100456,8 +100446,8 @@
100456
100446
  });
100457
100447
  return;
100458
100448
  }
100459
- const cacheKey = secretKey ? "".concat(apiBaseUrl, "|__key__") : "".concat(apiBaseUrl, "|").concat(orgId);
100460
- const cached = _PROCESS_CACHE.get(cacheKey);
100449
+ const key = "".concat(apiBaseUrl, "|").concat(orgId);
100450
+ const cached = _PROCESS_CACHE.get(key);
100461
100451
  if (cached) {
100462
100452
  setState({
100463
100453
  categories: cached,
@@ -100471,15 +100461,12 @@
100471
100461
  loading: true,
100472
100462
  error: null
100473
100463
  }));
100474
- const base = apiBaseUrl.replace(/\/$/, "");
100475
- const url = secretKey ? "".concat(base, "/api/v1/widget/filters") : "".concat(base, "/api/v1/widget/filters/").concat(encodeURIComponent(orgId));
100476
- const headers = {
100477
- Accept: "application/json"
100478
- };
100479
- if (secretKey) headers["x-eshal-key"] = secretKey;
100464
+ const url = "".concat(apiBaseUrl.replace(/\/$/, ""), "/api/v1/widget/filters/").concat(encodeURIComponent(orgId));
100480
100465
  fetch(url, {
100481
100466
  method: "GET",
100482
- headers
100467
+ headers: {
100468
+ Accept: "application/json"
100469
+ }
100483
100470
  }).then(async res => {
100484
100471
  if (!res.ok) {
100485
100472
  throw new Error("filter catalog HTTP ".concat(res.status));
@@ -100488,7 +100475,7 @@
100488
100475
  return Array.isArray(body === null || body === void 0 ? void 0 : body.categories) ? body.categories : [];
100489
100476
  }).then(categories => {
100490
100477
  if (cancelled) return;
100491
- _PROCESS_CACHE.set(cacheKey, categories);
100478
+ _PROCESS_CACHE.set(key, categories);
100492
100479
  setState({
100493
100480
  categories,
100494
100481
  loading: false,
@@ -100510,7 +100497,7 @@
100510
100497
  return () => {
100511
100498
  cancelled = true;
100512
100499
  };
100513
- }, [apiBaseUrl, orgId, secretKey]);
100500
+ }, [apiBaseUrl, orgId]);
100514
100501
  const hasFilters = reactExports.useMemo(() => Array.isArray(state.categories) && state.categories.length > 0, [state.categories]);
100515
100502
  return _objectSpread2(_objectSpread2({}, state), {}, {
100516
100503
  hasFilters
@@ -100592,25 +100579,17 @@
100592
100579
  * @param {string} orgId - Organization ID
100593
100580
  * @returns {Promise<object>} Agent configuration object
100594
100581
  */
100595
- const fetchAgentConfig = async (apiBaseUrl, orgId, secretKey) => {
100596
- if (!apiBaseUrl) {
100597
- throw new Error("apiBaseUrl is required");
100598
- }
100599
- if (!secretKey && !orgId) {
100600
- throw new Error("secretKey or orgId is required");
100582
+ const fetchAgentConfig = async (apiBaseUrl, orgId) => {
100583
+ if (!apiBaseUrl || !orgId) {
100584
+ throw new Error("apiBaseUrl and orgId are required");
100601
100585
  }
100602
100586
  try {
100603
- const base = apiBaseUrl.replace(/\/$/, '');
100604
- // Mode A/B: no orgId in URL — backend resolves org from x-eshal-key or HMAC sig
100605
- // Mode C legacy: orgId in URL path, no header needed
100606
- const url = secretKey ? "".concat(base, "/api/v1/deploy-agent") : "".concat(base, "/api/v1/deploy-agent/").concat(orgId);
100607
- const headers = {
100608
- "Content-Type": "application/json"
100609
- };
100610
- if (secretKey) headers['x-eshal-key'] = secretKey;
100587
+ const url = "".concat(apiBaseUrl.replace(/\/$/, ''), "/api/v1/deploy-agent/").concat(orgId);
100611
100588
  const response = await fetch(url, {
100612
100589
  method: "GET",
100613
- headers,
100590
+ headers: {
100591
+ "Content-Type": "application/json"
100592
+ },
100614
100593
  credentials: "include"
100615
100594
  });
100616
100595
  if (!response.ok) {
@@ -100627,11 +100606,8 @@
100627
100606
  const ChatWidget = _ref => {
100628
100607
  var _agentConfig$concierg;
100629
100608
  let {
100630
- // Auth — at least one of secretKey (Mode A/B) or orgId (Mode C legacy) is needed.
100631
- secretKey,
100632
- // sk_live_... from ChatWidget.init({ secretKey, apiBaseUrl })
100609
+ // Required props for dynamic config
100633
100610
  orgId,
100634
- // legacy — kept for backward compatibility
100635
100611
  apiBaseUrl,
100636
100612
  // Optional override props (will override fetched config if provided)
100637
100613
  darkMode,
@@ -100682,21 +100658,14 @@
100682
100658
  // Fetch agent configuration on mount
100683
100659
  reactExports.useEffect(() => {
100684
100660
  const loadAgentConfig = async () => {
100685
- if (!apiBaseUrl) {
100686
- setConfigError("apiBaseUrl is required");
100687
- setIsLoadingConfig(false);
100688
- return;
100689
- }
100690
- if (!secretKey && !orgId) {
100691
- setConfigError("secretKey or orgId is required");
100661
+ if (!orgId || !apiBaseUrl) {
100662
+ setConfigError("orgId and apiBaseUrl are required");
100692
100663
  setIsLoadingConfig(false);
100693
100664
  return;
100694
100665
  }
100695
100666
  try {
100696
100667
  setIsLoadingConfig(true);
100697
- // Pass secretKey for Mode A/B — fetchAgentConfig will send it as a
100698
- // header and omit the orgId path segment. Pass orgId for Mode C legacy.
100699
- const config = await fetchAgentConfig(apiBaseUrl, orgId, secretKey);
100668
+ const config = await fetchAgentConfig(apiBaseUrl, orgId);
100700
100669
  setAgentConfig(config);
100701
100670
  setConfigError(null);
100702
100671
  } catch (error) {
@@ -100707,7 +100676,7 @@
100707
100676
  }
100708
100677
  };
100709
100678
  loadAgentConfig();
100710
- }, [orgId, secretKey, apiBaseUrl]);
100679
+ }, [orgId, apiBaseUrl]);
100711
100680
 
100712
100681
  // Map API response to widget props (use props as overrides if provided)
100713
100682
  const widgetConfig = reactExports.useMemo(() => {
@@ -100885,7 +100854,6 @@
100885
100854
  // knowledge-api LoadBalancer.
100886
100855
  apiKey,
100887
100856
  organizationId: widgetConfig.organizationId,
100888
- secretKey,
100889
100857
  autoOpen,
100890
100858
  openDelay,
100891
100859
  darkMode: widgetConfig.darkMode,
@@ -100912,15 +100880,14 @@
100912
100880
  // navigation (but not a page refresh — feedback is not written to
100913
100881
  // localStorage so it resets on reload as intended).
100914
100882
  updateMessageFeedback(messageContent, feedback);
100915
- if (!orgId && !secretKey || !conversationId || !apiBaseUrl) return;
100883
+ if (!orgId || !conversationId || !apiBaseUrl) return;
100916
100884
  const base = apiBaseUrl.replace(/\/$/, "");
100917
- const feedbackHeaders = {
100918
- "Content-Type": "application/json"
100919
- };
100920
- if (secretKey) feedbackHeaders['x-eshal-key'] = secretKey;else if (orgId) feedbackHeaders['x-eshal-org'] = orgId;
100921
100885
  fetch("".concat(base, "/api/v1/support/feedback"), {
100922
100886
  method: "POST",
100923
- headers: feedbackHeaders,
100887
+ headers: {
100888
+ "Content-Type": "application/json",
100889
+ "x-eshal-org": orgId
100890
+ },
100924
100891
  credentials: "include",
100925
100892
  body: JSON.stringify({
100926
100893
  messageContent,
@@ -100946,7 +100913,7 @@
100946
100913
  const {
100947
100914
  categories: filterCategories,
100948
100915
  hasFilters: showFilterStep
100949
- } = useFilterCatalog(apiBaseUrl, orgId, secretKey);
100916
+ } = useFilterCatalog(apiBaseUrl, orgId);
100950
100917
 
100951
100918
  // Copy chat handler — copy all messages to clipboard
100952
100919
  const handleCopyChat = reactExports.useCallback(() => {
@@ -101052,7 +101019,6 @@
101052
101019
  apiBaseUrl: apiBaseUrl,
101053
101020
  apiKey: apiKey,
101054
101021
  organizationId: widgetConfig.organizationId,
101055
- secretKey: secretKey,
101056
101022
  conversationId: conversationId,
101057
101023
  conciergeId: (_agentConfig$concierg = agentConfig === null || agentConfig === void 0 ? void 0 : agentConfig.conciergeId) !== null && _agentConfig$concierg !== void 0 ? _agentConfig$concierg : agentConfig === null || agentConfig === void 0 ? void 0 : agentConfig.id,
101058
101024
  onboardingQuestions: widgetConfig.onboardingQuestions,
@@ -101200,14 +101166,11 @@
101200
101166
  }
101201
101167
 
101202
101168
  // Render component
101203
- // Mode A/B: secretKey present — orgId derived server-side from the key
101204
- // Mode C legacy: orgId in config — backward compatible
101205
- // Both: apiBaseUrl required
101206
- const hasNewAuth = (config.secretKey || config.orgId) && config.apiBaseUrl;
101207
- const widgetProps = hasNewAuth ? _objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({
101208
- // Auth props — secretKey replaces orgId in Mode A/B
101209
- secretKey: config.secretKey || null,
101210
- orgId: config.orgId || null,
101169
+ // If orgId and apiBaseUrl are provided, use dynamic config
101170
+ // Otherwise, use the old static config approach for backward compatibility
101171
+ const widgetProps = config.orgId && config.apiBaseUrl ? _objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({
101172
+ // Required props
101173
+ orgId: config.orgId,
101211
101174
  apiBaseUrl: config.apiBaseUrl
101212
101175
  }, options.wsBaseUrl !== undefined && {
101213
101176
  wsBaseUrl: config.wsBaseUrl