@iblai/web-utils 0.3.0 → 1.1.1

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.
Files changed (41) hide show
  1. package/README.md +504 -0
  2. package/dist/data-layer/src/features/chat-files/api-slice.d.ts +185 -0
  3. package/dist/data-layer/src/features/chat-files/types.d.ts +32 -0
  4. package/dist/data-layer/src/features/core/api-slice.d.ts +419 -61
  5. package/dist/data-layer/src/features/core/constants.d.ts +3 -0
  6. package/dist/data-layer/src/features/core/custom-api-slice.d.ts +50 -50
  7. package/dist/data-layer/src/features/core/custom-public-image-asset-api-slice.d.ts +333 -0
  8. package/dist/data-layer/src/features/core/types.d.ts +33 -0
  9. package/dist/data-layer/src/features/credentials/api-slice.d.ts +62 -39
  10. package/dist/data-layer/src/features/mentor/api-slice.d.ts +1028 -188
  11. package/dist/data-layer/src/features/notifications/constants.d.ts +6 -0
  12. package/dist/data-layer/src/features/notifications/custom-api-slice.d.ts +43 -43
  13. package/dist/data-layer/src/features/notifications/types.d.ts +25 -2
  14. package/dist/data-layer/src/features/stripe/api-slice.d.ts +22 -0
  15. package/dist/data-layer/src/index.d.ts +3 -0
  16. package/dist/index.d.ts +447 -83
  17. package/dist/index.esm.js +1137 -196
  18. package/dist/index.esm.js.map +1 -1
  19. package/dist/index.js +1167 -193
  20. package/dist/index.js.map +1 -1
  21. package/dist/package.json +4 -2
  22. package/dist/web-utils/src/constants/chat.d.ts +8 -0
  23. package/dist/web-utils/src/features/files/filesSlice.d.ts +20 -0
  24. package/dist/web-utils/src/features/index.d.ts +1 -0
  25. package/dist/web-utils/src/hooks/chat/use-advanced-chat.d.ts +6 -4
  26. package/dist/web-utils/src/hooks/chat/use-chat-v2.d.ts +11 -1
  27. package/dist/web-utils/src/hooks/use-mentor-settings.d.ts +18 -15
  28. package/dist/web-utils/src/index.d.ts +2 -0
  29. package/dist/web-utils/src/index.web.d.ts +14 -12
  30. package/dist/web-utils/src/providers/auth-provider.d.ts +9 -1
  31. package/dist/web-utils/src/providers/mentor-provider.d.ts +2 -1
  32. package/dist/web-utils/src/providers/tenant-provider.d.ts +3 -1
  33. package/dist/web-utils/src/services/__tests__/file-upload.test.d.ts +1 -0
  34. package/dist/web-utils/src/services/file-upload.d.ts +60 -0
  35. package/dist/web-utils/src/services/index.d.ts +1 -0
  36. package/dist/web-utils/src/types/file-upload.d.ts +62 -0
  37. package/dist/web-utils/src/types/index.d.ts +1 -0
  38. package/dist/web-utils/src/utils/auth.d.ts +180 -0
  39. package/dist/web-utils/src/utils/index.d.ts +1 -0
  40. package/package.json +12 -13
  41. package/dist/web-utils/tsconfig.tsbuildinfo +0 -1
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@
3
3
  var React = require('react');
4
4
  var iblaiApi = require('@iblai/iblai-api');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
+ var axios = require('axios');
6
7
 
7
8
  function _interopNamespaceDefault(e) {
8
9
  var n = Object.create(null);
@@ -3400,7 +3401,7 @@ function updateMutationSubstateIfExists(state, id, update) {
3400
3401
  update(substate);
3401
3402
  }
3402
3403
  }
3403
- var initialState$1 = {};
3404
+ var initialState$2 = {};
3404
3405
  function buildSlice({
3405
3406
  reducerPath,
3406
3407
  queryThunk,
@@ -3476,7 +3477,7 @@ function buildSlice({
3476
3477
  }
3477
3478
  const querySlice = createSlice$1({
3478
3479
  name: `${reducerPath}/queries`,
3479
- initialState: initialState$1,
3480
+ initialState: initialState$2,
3480
3481
  reducers: {
3481
3482
  removeQueryResult: {
3482
3483
  reducer(draft, {
@@ -3610,7 +3611,7 @@ function buildSlice({
3610
3611
  });
3611
3612
  const mutationSlice = createSlice$1({
3612
3613
  name: `${reducerPath}/mutations`,
3613
- initialState: initialState$1,
3614
+ initialState: initialState$2,
3614
3615
  reducers: {
3615
3616
  removeMutationResult: {
3616
3617
  reducer(draft, {
@@ -3779,7 +3780,7 @@ function buildSlice({
3779
3780
  }
3780
3781
  const subscriptionSlice = createSlice$1({
3781
3782
  name: `${reducerPath}/subscriptions`,
3782
- initialState: initialState$1,
3783
+ initialState: initialState$2,
3783
3784
  reducers: {
3784
3785
  updateSubscriptionOptions(d, a) {
3785
3786
  },
@@ -3791,7 +3792,7 @@ function buildSlice({
3791
3792
  });
3792
3793
  const internalSubscriptionsSlice = createSlice$1({
3793
3794
  name: `${reducerPath}/internalSubscriptions`,
3794
- initialState: initialState$1,
3795
+ initialState: initialState$2,
3795
3796
  reducers: {
3796
3797
  subscriptionsUpdated: {
3797
3798
  reducer(state, action) {
@@ -6461,6 +6462,25 @@ createApi({
6461
6462
  }),
6462
6463
  });
6463
6464
 
6465
+ createApi({
6466
+ reducerPath: 'chatFilesApiSlice',
6467
+ baseQuery: iblFetchBaseQuery,
6468
+ endpoints: (builder) => ({
6469
+ /**
6470
+ * Get presigned S3 URL for file upload
6471
+ * POST /api/ai-mentor/orgs/{org}/users/{userId}/chat/files/upload-url/
6472
+ */
6473
+ getFileUploadUrl: builder.mutation({
6474
+ query: ({ org, userId, requestBody, }) => ({
6475
+ url: `/api/ai-mentor/orgs/${org}/users/${userId}/chat/files/upload-url/`,
6476
+ method: 'POST',
6477
+ body: requestBody,
6478
+ service: SERVICES.DM,
6479
+ }),
6480
+ }),
6481
+ }),
6482
+ });
6483
+
6464
6484
  createApi({
6465
6485
  reducerPath: 'llmsApiSlice',
6466
6486
  baseQuery: iblFakeBaseQuery,
@@ -6481,6 +6501,7 @@ const mentorApiSlice = createApi({
6481
6501
  'mentorPublicSettings',
6482
6502
  'shareableLinks',
6483
6503
  'publicMentors',
6504
+ 'moderationLogs',
6484
6505
  ],
6485
6506
  endpoints: (builder) => ({
6486
6507
  createMentor: builder.mutation({
@@ -6546,7 +6567,7 @@ const mentorApiSlice = createApi({
6546
6567
  }));
6547
6568
  }
6548
6569
  catch (error) {
6549
- console.error(error);
6570
+ console.error(JSON.stringify(error));
6550
6571
  }
6551
6572
  },
6552
6573
  }),
@@ -6602,9 +6623,17 @@ const mentorApiSlice = createApi({
6602
6623
  ...buildEndpointFromDmService(iblaiApi.AiMentorService.aiMentorOrgsUsersMentorsForkCreate),
6603
6624
  invalidatesTags: ['mentors'],
6604
6625
  }),
6626
+ getRecentlyAccessedMentors: builder.query({
6627
+ ...buildEndpointFromDmService(iblaiApi.AiMentorService.aiMentorOrgsUsersRecentlyAccessedMentorsList),
6628
+ providesTags: ['mentors'],
6629
+ }),
6630
+ getModerationLogs: builder.query({
6631
+ ...buildEndpointFromDmService(iblaiApi.AiMentorService.aiMentorOrgsUsersModerationLogsList),
6632
+ providesTags: ['moderationLogs'],
6633
+ }),
6605
6634
  }),
6606
6635
  });
6607
- const { useLazyGetMentorsQuery, useLazySeedMentorsQuery, useGetMentorSettingsQuery, useGetMentorPublicSettingsQuery, useLazyGetMentorPublicSettingsQuery, useLazyGetFreeUsageCountQuery} = mentorApiSlice;
6636
+ const { useLazyGetMentorsQuery, useLazySeedMentorsQuery, useGetMentorSettingsQuery, useGetMentorPublicSettingsQuery, useLazyGetMentorPublicSettingsQuery, useLazyGetFreeUsageCountQuery, useLazyGetRecentlyAccessedMentorsQuery} = mentorApiSlice;
6608
6637
 
6609
6638
  createApi({
6610
6639
  reducerPath: 'mentorCategoriesApiSlice',
@@ -7071,7 +7100,20 @@ const coreApiSlice = createApi({
7071
7100
  invalidatesTags: ['RbacGroups'],
7072
7101
  }),
7073
7102
  getRbacGroupDetails: builder.query({
7074
- ...buildEndpointFromDmService(iblaiApi.CoreService.coreRbacGroupsRetrieve),
7103
+ ...buildEndpointFromService(SERVICES.DM, async (args) => {
7104
+ const url = `${iblaiApi.OpenAPI.BASE}/api/core/rbac/groups/${args.id}/`;
7105
+ const response = await fetch(url, {
7106
+ method: 'GET',
7107
+ headers: iblaiApi.OpenAPI.HEADERS,
7108
+ });
7109
+ if (!response.ok) {
7110
+ const error = new Error('Failed to fetch RBAC group details');
7111
+ error.status = response.status;
7112
+ error.body = await response.text();
7113
+ throw error;
7114
+ }
7115
+ return response.json();
7116
+ }),
7075
7117
  providesTags: ['RbacGroups'],
7076
7118
  }),
7077
7119
  //RBAC POLICIES
@@ -7092,7 +7134,22 @@ const coreApiSlice = createApi({
7092
7134
  invalidatesTags: ['RbacPolicies'],
7093
7135
  }),
7094
7136
  getRbacPolicyDetails: builder.query({
7095
- ...buildEndpointFromDmService(iblaiApi.CoreService.coreRbacPoliciesRetrieve),
7137
+ ...buildEndpointFromService(SERVICES.DM, async (args) => {
7138
+ const queryParams = new URLSearchParams({ platform_key: args.platform_key });
7139
+ const queryString = queryParams.toString();
7140
+ const url = `${iblaiApi.OpenAPI.BASE}/api/core/rbac/policies/${args.id}/?${queryString}`;
7141
+ const response = await fetch(url, {
7142
+ method: 'GET',
7143
+ headers: iblaiApi.OpenAPI.HEADERS,
7144
+ });
7145
+ if (!response.ok) {
7146
+ const error = new Error('Failed to fetch RBAC policy details');
7147
+ error.status = response.status;
7148
+ error.body = await response.text();
7149
+ throw error;
7150
+ }
7151
+ return response.json();
7152
+ }),
7096
7153
  providesTags: ['RbacPolicies'],
7097
7154
  }),
7098
7155
  //RBAC ROLES
@@ -7117,14 +7174,36 @@ const coreApiSlice = createApi({
7117
7174
  invalidatesTags: ['RbacRoles'],
7118
7175
  }),
7119
7176
  getRbacRoleDetails: builder.query({
7120
- ...buildEndpointFromDmService(iblaiApi.CoreService.coreRbacRolesRetrieve),
7177
+ ...buildEndpointFromService(SERVICES.DM, async (args) => {
7178
+ const queryParams = new URLSearchParams({ platform_key: args.platform_key });
7179
+ const queryString = queryParams.toString();
7180
+ const url = `${iblaiApi.OpenAPI.BASE}/api/core/rbac/roles/${args.id}/?${queryString}`;
7181
+ const response = await fetch(url, {
7182
+ method: 'GET',
7183
+ headers: iblaiApi.OpenAPI.HEADERS,
7184
+ });
7185
+ if (!response.ok) {
7186
+ const error = new Error('Failed to fetch RBAC role details');
7187
+ error.status = response.status;
7188
+ error.body = await response.text();
7189
+ throw error;
7190
+ }
7191
+ return response.json();
7192
+ }),
7121
7193
  providesTags: ['RbacRoles'],
7122
7194
  }),
7195
+ getRbacMentorAccessList: builder.query({
7196
+ ...buildEndpointFromDmService(iblaiApi.CoreService.coreRbacMentorAccessList),
7197
+ }),
7198
+ updateRbacMentorAccess: builder.mutation({
7199
+ ...buildEndpointFromDmService(iblaiApi.CoreService.coreRbacMentorAccessCreate),
7200
+ }),
7123
7201
  }),
7124
7202
  });
7125
7203
  const { useGetRbacPermissionsMutation} = coreApiSlice;
7126
7204
 
7127
7205
  const CORE_CUSTOM_REDUCER_PATH = 'coreCustomApiSlice';
7206
+ const CORE_FAKE_CUSTOM_REDUCER_PATH = 'coreFakeCustomApiSlice';
7128
7207
  const PLATFORM_MEMBERSHIP_TAG = 'PlatformMembership';
7129
7208
  const CORE_CUSTOM_ENDPOINTS = {
7130
7209
  GET_PLATFORM_MEMBERSHIP: {
@@ -7158,7 +7237,13 @@ const CORE_CUSTOM_ENDPOINTS = {
7158
7237
  DELETE_PLATFORM_IMAGE_ASSET: {
7159
7238
  path: (platform_key, asset_id) => `/api/core/platforms/${platform_key}/public-image-assets/${asset_id}/`,
7160
7239
  service: SERVICES.DM,
7161
- }};
7240
+ },
7241
+ GET_PUBLIC_PLATFORM_IMAGE_ASSET_FILE_URL: {
7242
+ path: (platform_key, asset_id) => `/api/core/platforms/${platform_key}/public-image-assets/${asset_id}/file/`,
7243
+ baseUrl: getServiceUrl(SERVICES.DM),
7244
+ service: SERVICES.DM,
7245
+ },
7246
+ };
7162
7247
 
7163
7248
  createApi({
7164
7249
  // TODO: replace to catalogSlice
@@ -7230,7 +7315,13 @@ createApi({
7230
7315
  ...buildEndpointFromDmService(iblaiApi.AiAccountService.aiAccountOrgsIntegrationCredentialPartialUpdate),
7231
7316
  }),
7232
7317
  getConnectedServiceAuthUrl: builder.query({
7233
- ...buildEndpointFromDmService(iblaiApi.AiAccountService.aiAccountConnectedServicesOrgsUsersRetrieve),
7318
+ queryFn: async (queryParams, api, extraOptions) => {
7319
+ const url = `/api/ai-account/connected-services/orgs/${queryParams.org}/users/${queryParams.userId}/${queryParams.provider}/${queryParams.service}/`;
7320
+ return iblFetchBaseQuery({
7321
+ url,
7322
+ service: SERVICES.DM,
7323
+ }, api, extraOptions);
7324
+ },
7234
7325
  }),
7235
7326
  connectedServicesCallback: builder.query({
7236
7327
  queryFn: async (queryParams, api, extraOptions) => {
@@ -7324,10 +7415,11 @@ const stripeApiSlice = createApi({
7324
7415
  providesTags: ['stripe-context'],
7325
7416
  }),
7326
7417
  getStripePricingPageSession: builder.query({
7327
- query: ({ platform_key }) => ({
7418
+ query: ({ platform_key, params }) => ({
7328
7419
  url: STRIPE_ENDPOINTS.GET_STRIPE_PRICING_PAGE_SESSION.path(platform_key),
7329
7420
  service: STRIPE_ENDPOINTS.GET_STRIPE_PRICING_PAGE_SESSION.service,
7330
7421
  method: 'GET',
7422
+ params,
7331
7423
  }),
7332
7424
  providesTags: ['stripe-context'],
7333
7425
  }),
@@ -7362,7 +7454,7 @@ const sessionApiSlice = createApi({
7362
7454
  }),
7363
7455
  }),
7364
7456
  });
7365
- const { useCreateSessionIdMutation, useEditSessionMutation, } = sessionApiSlice;
7457
+ const { useCreateSessionIdMutation, useLazyGetSessionIdQuery, useEditSessionMutation, } = sessionApiSlice;
7366
7458
 
7367
7459
  createApi({
7368
7460
  reducerPath: 'datasetsApiSlice',
@@ -8299,6 +8391,12 @@ createApi({
8299
8391
  });
8300
8392
 
8301
8393
  const NOTIFICATIONS_CUSTOM_REDUCER_PATH = 'notificationsCustomApiSlice';
8394
+ const NOTIFICATIONS_CUSTOM_TAGS = {
8395
+ TEMPLATES: 'NOTIFICATIONS_CUSTOM_TEMPLATES',
8396
+ TEMPLATE_DETAILS: 'NOTIFICATIONS_CUSTOM_TEMPLATE_DETAILS',
8397
+ UPDATE_TEMPLATE: 'NOTIFICATIONS_CUSTOM_UPDATE_TEMPLATE',
8398
+ TOGGLE_TEMPLATE: 'NOTIFICATIONS_CUSTOM_TOGGLE_TEMPLATE',
8399
+ };
8302
8400
  const NOTIFICATIONS_CUSTOM_ENDPOINTS = {
8303
8401
  GET_TEMPLATES: {
8304
8402
  service: SERVICES.DM,
@@ -8320,6 +8418,7 @@ const NOTIFICATIONS_CUSTOM_ENDPOINTS = {
8320
8418
 
8321
8419
  createApi({
8322
8420
  reducerPath: NOTIFICATIONS_CUSTOM_REDUCER_PATH,
8421
+ tagTypes: [...Object.values(NOTIFICATIONS_CUSTOM_TAGS)],
8323
8422
  baseQuery: iblFetchBaseQuery,
8324
8423
  endpoints: (builder) => ({
8325
8424
  getTemplates: builder.query({
@@ -8329,6 +8428,7 @@ createApi({
8329
8428
  service: NOTIFICATIONS_CUSTOM_ENDPOINTS.GET_TEMPLATES.service,
8330
8429
  };
8331
8430
  },
8431
+ providesTags: [NOTIFICATIONS_CUSTOM_TAGS.TEMPLATES],
8332
8432
  }),
8333
8433
  getTemplateDetails: builder.query({
8334
8434
  query: (args) => {
@@ -8337,6 +8437,7 @@ createApi({
8337
8437
  service: NOTIFICATIONS_CUSTOM_ENDPOINTS.GET_TEMPLATE_DETAILS.service,
8338
8438
  };
8339
8439
  },
8440
+ providesTags: [NOTIFICATIONS_CUSTOM_TAGS.TEMPLATE_DETAILS],
8340
8441
  }),
8341
8442
  updateTemplate: builder.mutation({
8342
8443
  query: (args) => {
@@ -8347,6 +8448,7 @@ createApi({
8347
8448
  body: args.template,
8348
8449
  };
8349
8450
  },
8451
+ invalidatesTags: [NOTIFICATIONS_CUSTOM_TAGS.TEMPLATE_DETAILS],
8350
8452
  }),
8351
8453
  toggleTemplate: builder.mutation({
8352
8454
  query: (args) => {
@@ -8359,6 +8461,7 @@ createApi({
8359
8461
  },
8360
8462
  };
8361
8463
  },
8464
+ invalidatesTags: [NOTIFICATIONS_CUSTOM_TAGS.TEMPLATES],
8362
8465
  }),
8363
8466
  }),
8364
8467
  });
@@ -8639,7 +8742,7 @@ const CUSTOM_DOMAIN_QUERY_KEYS = {
8639
8742
  CREATE_CUSTOM_DOMAIN: () => ['CREATE_CUSTOM_DOMAIN'],
8640
8743
  };
8641
8744
 
8642
- createApi({
8745
+ const customDomainApiSlice = createApi({
8643
8746
  reducerPath: CUSTOM_DOMAIN_REDUCER_PATH,
8644
8747
  baseQuery: iblFetchBaseQuery,
8645
8748
  tagTypes: [...CUSTOM_DOMAIN_QUERY_KEYS.GET_CUSTOM_DOMAINS()],
@@ -8678,6 +8781,7 @@ createApi({
8678
8781
  }),
8679
8782
  }),
8680
8783
  });
8784
+ const { useGetCustomDomainsQuery} = customDomainApiSlice;
8681
8785
 
8682
8786
  const PLATFORM_CUSTOM_REDUCER_PATH = "platformCustomApiSlice";
8683
8787
  const PLATFORM_CONFIGURATION_TAG = "PlatformConfiguration";
@@ -8740,7 +8844,7 @@ createApi({
8740
8844
  const coreCustomApiSlice = createApi({
8741
8845
  reducerPath: CORE_CUSTOM_REDUCER_PATH,
8742
8846
  baseQuery: iblFetchBaseQuery,
8743
- tagTypes: [PLATFORM_MEMBERSHIP_TAG],
8847
+ tagTypes: [PLATFORM_MEMBERSHIP_TAG, 'PlatformImageAssetFileUrl'],
8744
8848
  endpoints: (builder) => ({
8745
8849
  getPlatformMembership: builder.query({
8746
8850
  query: ({ platform_key }) => ({
@@ -8813,6 +8917,19 @@ const coreCustomApiSlice = createApi({
8813
8917
  });
8814
8918
  const { useJoinTenantMutation} = coreCustomApiSlice;
8815
8919
 
8920
+ createApi({
8921
+ reducerPath: CORE_FAKE_CUSTOM_REDUCER_PATH,
8922
+ baseQuery: iblFakeBaseQuery,
8923
+ endpoints: (builder) => ({
8924
+ getPublicPlatformImageAssetFileUrl: builder.query({
8925
+ ...buildEndpointFromService(SERVICES.DM, async (args) => {
8926
+ const url = `${iblaiApi.OpenAPI.BASE}${CORE_CUSTOM_ENDPOINTS.GET_PUBLIC_PLATFORM_IMAGE_ASSET_FILE_URL.path(args.platform_key, args.asset_id)}`;
8927
+ return url;
8928
+ }),
8929
+ }),
8930
+ }),
8931
+ });
8932
+
8816
8933
  const EDX_PROCTORING_ENDPOINTS = {
8817
8934
  GET_EXAM_INFO: {
8818
8935
  service: SERVICES.LMS,
@@ -9735,6 +9852,7 @@ const useSubscriptionHandlerV2 = (subscriptionFlow) => {
9735
9852
  });
9736
9853
  }
9737
9854
  catch (error) {
9855
+ console.error("Error getting user active app:", JSON.stringify(error));
9738
9856
  return null;
9739
9857
  }
9740
9858
  };
@@ -9781,6 +9899,7 @@ const useSubscriptionHandlerV2 = (subscriptionFlow) => {
9781
9899
  return await getUserActiveApp();
9782
9900
  }
9783
9901
  catch (error) {
9902
+ console.error("Error updating trial status:", JSON.stringify(error));
9784
9903
  return null;
9785
9904
  }
9786
9905
  };
@@ -9873,6 +9992,7 @@ const useSubscriptionHandlerV2 = (subscriptionFlow) => {
9873
9992
  return stripeContext.payment_link_url;
9874
9993
  }
9875
9994
  catch (error) {
9995
+ console.error("Error getting top up URL:", JSON.stringify(error));
9876
9996
  return null;
9877
9997
  }
9878
9998
  };
@@ -9946,6 +10066,7 @@ const useSubscriptionHandlerV2 = (subscriptionFlow) => {
9946
10066
  return stripeCustomerPortal === null || stripeCustomerPortal === void 0 ? void 0 : stripeCustomerPortal.url;
9947
10067
  }
9948
10068
  catch (error) {
10069
+ console.error("Error getting billing URL:", JSON.stringify(error));
9949
10070
  return null;
9950
10071
  }
9951
10072
  };
@@ -9991,7 +10112,10 @@ const useSubscriptionHandlerV2 = (subscriptionFlow) => {
9991
10112
  try {
9992
10113
  subscriptionFlow.handleBeforePricingPageDisplayFlow();
9993
10114
  const { data: stripeContext } = await getStripePricingPageSession({
9994
- platform_key: subscriptionFlow.getCurrentTenantKey(),
10115
+ platform_key: subscriptionFlow.getMainTenantKey(),
10116
+ params: {
10117
+ source_platform_key: subscriptionFlow.getCurrentTenantKey(),
10118
+ },
9995
10119
  }, false);
9996
10120
  if (isStripeContextError ||
9997
10121
  !stripeContext ||
@@ -10004,6 +10128,7 @@ const useSubscriptionHandlerV2 = (subscriptionFlow) => {
10004
10128
  }, !hasCredits);
10005
10129
  }
10006
10130
  catch (error) {
10131
+ console.error("Error getting stripe pricing page session:", JSON.stringify(error));
10007
10132
  subscriptionFlow.handleFailureOnPaymentFlow();
10008
10133
  }
10009
10134
  };
@@ -10325,6 +10450,299 @@ const formatRelativeTime = (timestamp) => {
10325
10450
  return `${diffInYears} year${diffInYears === 1 ? "" : "s"} ago`;
10326
10451
  };
10327
10452
 
10453
+ /**
10454
+ * Authentication and Authorization Utilities
10455
+ *
10456
+ * This module provides utility functions for handling authentication flows,
10457
+ * including redirects to auth SPA, cookie management, and session handling.
10458
+ */
10459
+ /**
10460
+ * Check if the current window is inside an iframe
10461
+ * @returns {boolean} True if running in an iframe, false otherwise
10462
+ */
10463
+ function isInIframe() {
10464
+ if (typeof window === "undefined") {
10465
+ return false;
10466
+ }
10467
+ return (window === null || window === void 0 ? void 0 : window.self) !== (window === null || window === void 0 ? void 0 : window.top);
10468
+ }
10469
+ /**
10470
+ * Send a message to the parent website (when in iframe)
10471
+ * @param payload - The data to send to parent window
10472
+ */
10473
+ function sendMessageToParentWebsite(payload) {
10474
+ window.parent.postMessage(payload, "*");
10475
+ }
10476
+ /**
10477
+ * Delete a cookie with specific name, path, and domain
10478
+ * @param name - Cookie name
10479
+ * @param path - Cookie path
10480
+ * @param domain - Cookie domain
10481
+ */
10482
+ function deleteCookie(name, path, domain) {
10483
+ const expires = "expires=Thu, 01 Jan 1970 00:00:00 UTC;";
10484
+ const cookieValue = `${name}=;`;
10485
+ const pathValue = path ? `path=${path};` : "";
10486
+ const domainValue = domain ? `domain=${domain};` : "";
10487
+ document.cookie = cookieValue + expires + pathValue + domainValue;
10488
+ }
10489
+ /**
10490
+ * Get all possible domain parts for cookie deletion
10491
+ * @param domain - The domain to split
10492
+ * @returns Array of domain parts
10493
+ * @example
10494
+ * getDomainParts('app.example.com') // returns ['app.example.com', 'example.com', 'com']
10495
+ */
10496
+ function getDomainParts(domain) {
10497
+ const parts = domain.split(".");
10498
+ const domains = [];
10499
+ for (let i = parts.length - 1; i >= 0; i--) {
10500
+ domains.push(parts.slice(i).join("."));
10501
+ }
10502
+ return domains;
10503
+ }
10504
+ /**
10505
+ * Delete a cookie across all possible domain variations
10506
+ * @param name - Cookie name to delete
10507
+ * @param childDomain - The current domain
10508
+ */
10509
+ function deleteCookieOnAllDomains(name, childDomain) {
10510
+ getDomainParts(childDomain).forEach((domainPart) => {
10511
+ deleteCookie(name, "/", domainPart);
10512
+ deleteCookie(name, "", domainPart);
10513
+ });
10514
+ }
10515
+ /**
10516
+ * Get the parent domain from a given domain
10517
+ * @param domain - The domain to process
10518
+ * @returns The parent domain (e.g., 'app.example.com' → '.example.com')
10519
+ */
10520
+ function getParentDomain(domain) {
10521
+ if (!domain) {
10522
+ return "";
10523
+ }
10524
+ const parts = domain.split(".");
10525
+ return parts.length > 1 ? `.${parts.slice(-2).join(".")}` : domain;
10526
+ }
10527
+ /**
10528
+ * Set a cookie for authentication with cross-domain support
10529
+ * @param name - Cookie name
10530
+ * @param value - Cookie value
10531
+ * @param days - Number of days until expiration (default: 365)
10532
+ */
10533
+ function setCookieForAuth(name, value, days = 365) {
10534
+ const expires = new Date();
10535
+ expires.setTime(expires.getTime() + days * 24 * 60 * 60 * 1000);
10536
+ const hostname = window.location.hostname;
10537
+ let baseDomain = hostname;
10538
+ // Calculate base domain (skip for localhost and IP addresses)
10539
+ if (hostname !== "localhost" && !/^\d+\.\d+\.\d+\.\d+$/.test(hostname)) {
10540
+ const parts = hostname.split(".");
10541
+ if (parts.length > 2) {
10542
+ baseDomain = `.${parts.slice(-2).join(".")}`;
10543
+ }
10544
+ }
10545
+ const domainAttr = baseDomain ? `;domain=${baseDomain}` : "";
10546
+ document.cookie = `${name}=${encodeURIComponent(value)};expires=${expires.toUTCString()};path=/;SameSite=None;Secure${domainAttr}`;
10547
+ }
10548
+ /**
10549
+ * Clear all cookies for the current domain
10550
+ */
10551
+ function clearCookies() {
10552
+ const cookies = document.cookie.split(";");
10553
+ for (let i = 0; i < cookies.length; i++) {
10554
+ const cookie = cookies[i];
10555
+ const eqPos = cookie.indexOf("=");
10556
+ const name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
10557
+ deleteCookieOnAllDomains(name, window.location.hostname);
10558
+ document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;Domain=${getParentDomain(window.location.hostname)}`;
10559
+ }
10560
+ }
10561
+ /**
10562
+ * Check if user is currently logged in
10563
+ * @param tokenKey - The localStorage key for the auth token (default: 'axd_token')
10564
+ * @returns True if logged in, false otherwise
10565
+ */
10566
+ function isLoggedIn(tokenKey = "axd_token") {
10567
+ return !!localStorage.getItem(tokenKey);
10568
+ }
10569
+ /**
10570
+ * Extract platform/tenant key from URL
10571
+ * @param url - The URL to parse
10572
+ * @param pattern - RegExp pattern to match platform key (default matches /platform/[key]/...)
10573
+ * @returns The platform key or null if not found
10574
+ */
10575
+ function getPlatformKey(url, pattern = /\/platform\/([^/]+)/) {
10576
+ const match = url.match(pattern);
10577
+ return match ? match[1] : null;
10578
+ }
10579
+ /**
10580
+ * Redirect to authentication SPA for login/logout
10581
+ *
10582
+ * This function handles the complete authentication flow:
10583
+ * - Clears localStorage and cookies on logout
10584
+ * - Saves redirect path for post-auth return
10585
+ * - Handles iframe scenarios
10586
+ * - Syncs logout across multiple SPAs via cookies
10587
+ *
10588
+ * @param options - Configuration options for the redirect
10589
+ *
10590
+ * @example
10591
+ * ```tsx
10592
+ * // Basic usage
10593
+ * redirectToAuthSpa({
10594
+ * authUrl: 'https://auth.example.com',
10595
+ * appName: 'mentor',
10596
+ * });
10597
+ *
10598
+ * // With logout
10599
+ * redirectToAuthSpa({
10600
+ * authUrl: 'https://auth.example.com',
10601
+ * appName: 'mentor',
10602
+ * logout: true,
10603
+ * platformKey: 'my-tenant',
10604
+ * });
10605
+ *
10606
+ * // With custom redirect
10607
+ * redirectToAuthSpa({
10608
+ * authUrl: 'https://auth.example.com',
10609
+ * appName: 'mentor',
10610
+ * redirectTo: '/dashboard',
10611
+ * platformKey: 'my-tenant',
10612
+ * });
10613
+ * ```
10614
+ */
10615
+ async function redirectToAuthSpa(options) {
10616
+ const { redirectTo, platformKey, logout = false, saveRedirect = true, authUrl, appName, queryParams = {
10617
+ app: "app",
10618
+ redirectTo: "redirect-to",
10619
+ tenant: "tenant",
10620
+ }, redirectPathStorageKey = "redirect_to", cookieNames = {
10621
+ currentTenant: "ibl_current_tenant",
10622
+ userData: "ibl_user_data",
10623
+ tenant: "ibl_tenant",
10624
+ logoutTimestamp: "ibl_logout_timestamp",
10625
+ }, } = options;
10626
+ // Clear localStorage
10627
+ localStorage.clear();
10628
+ if (logout) {
10629
+ // Delete authentication cookies for cross-SPA synchronization
10630
+ const currentDomain = window.location.hostname;
10631
+ if (cookieNames.currentTenant) {
10632
+ deleteCookieOnAllDomains(cookieNames.currentTenant, currentDomain);
10633
+ }
10634
+ if (cookieNames.userData) {
10635
+ deleteCookieOnAllDomains(cookieNames.userData, currentDomain);
10636
+ }
10637
+ if (cookieNames.tenant) {
10638
+ deleteCookieOnAllDomains(cookieNames.tenant, currentDomain);
10639
+ }
10640
+ // Set logout timestamp cookie to trigger logout on other SPAs
10641
+ if (cookieNames.logoutTimestamp) {
10642
+ setCookieForAuth(cookieNames.logoutTimestamp, Date.now().toString());
10643
+ }
10644
+ }
10645
+ // Handle iframe scenario
10646
+ if (isInIframe()) {
10647
+ console.log("[redirectToAuthSpa]: sending authExpired to parent");
10648
+ sendMessageToParentWebsite({ authExpired: true });
10649
+ return;
10650
+ }
10651
+ const redirectPath = redirectTo !== null && redirectTo !== void 0 ? redirectTo : `${window.location.pathname}${window.location.search}`;
10652
+ // Never save sso-login routes as redirect paths
10653
+ if (!redirectPath.startsWith("/sso-login") && saveRedirect) {
10654
+ window.localStorage.setItem(redirectPathStorageKey, redirectPath);
10655
+ }
10656
+ const platform = platformKey !== null && platformKey !== void 0 ? platformKey : getPlatformKey(redirectPath);
10657
+ const redirectToUrl = `${window.location.origin}`;
10658
+ let authRedirectUrl = `${authUrl}/login?${queryParams.app}=${appName}`;
10659
+ authRedirectUrl += `&${queryParams.redirectTo}=${redirectToUrl}`;
10660
+ if (platform) {
10661
+ authRedirectUrl += `&${queryParams.tenant}=${platform}`;
10662
+ }
10663
+ if (logout) {
10664
+ authRedirectUrl += "&logout=1";
10665
+ }
10666
+ // Small delay for any pending operations
10667
+ await new Promise((resolve) => setTimeout(resolve, 100));
10668
+ // Redirect to auth SPA
10669
+ window.location.href = authRedirectUrl;
10670
+ }
10671
+ /**
10672
+ * Get the URL for joining a tenant (sign up flow)
10673
+ * @param authUrl - Auth SPA base URL
10674
+ * @param tenantKey - Tenant to join
10675
+ * @param redirectUrl - URL to redirect to after joining (defaults to current URL)
10676
+ * @returns The join URL
10677
+ */
10678
+ function getAuthSpaJoinUrl(authUrl, tenantKey, redirectUrl) {
10679
+ const resolvedTenant = tenantKey || getPlatformKey(window.location.pathname) || "";
10680
+ if (!resolvedTenant) {
10681
+ return "";
10682
+ }
10683
+ const targetUrl = redirectUrl !== null && redirectUrl !== void 0 ? redirectUrl : window.location.href;
10684
+ const joinUrl = `${authUrl}/join?tenant=${encodeURIComponent(resolvedTenant)}&redirect-to=${encodeURIComponent(targetUrl)}`;
10685
+ return joinUrl;
10686
+ }
10687
+ /**
10688
+ * Redirect to auth SPA's join/signup page for a specific tenant
10689
+ * @param authUrl - Auth SPA base URL
10690
+ * @param tenantKey - Tenant to join
10691
+ * @param redirectUrl - URL to redirect to after joining (defaults to current URL)
10692
+ */
10693
+ function redirectToAuthSpaJoinTenant(authUrl, tenantKey, redirectUrl) {
10694
+ const resolvedTenant = tenantKey || getPlatformKey(window.location.pathname) || "";
10695
+ if (!resolvedTenant) {
10696
+ console.log("[auth-redirect] Missing tenant key for join", {
10697
+ tenantKey,
10698
+ redirectUrl,
10699
+ });
10700
+ redirectToAuthSpa({
10701
+ authUrl,
10702
+ appName: "app", // Will need to be configured
10703
+ redirectTo: redirectUrl,
10704
+ });
10705
+ return;
10706
+ }
10707
+ const targetUrl = redirectUrl !== null && redirectUrl !== void 0 ? redirectUrl : window.location.href;
10708
+ const joinUrl = `${authUrl}/join?tenant=${encodeURIComponent(resolvedTenant)}&redirect-to=${encodeURIComponent(targetUrl)}`;
10709
+ window.location.href = joinUrl;
10710
+ }
10711
+ /**
10712
+ * Handle user logout
10713
+ *
10714
+ * This function:
10715
+ * - Clears localStorage (preserving tenant)
10716
+ * - Sets logout timestamp cookie for cross-SPA sync
10717
+ * - Clears all cookies
10718
+ * - Redirects to auth SPA logout endpoint
10719
+ *
10720
+ * @param options - Logout configuration options
10721
+ *
10722
+ * @example
10723
+ * ```tsx
10724
+ * handleLogout({
10725
+ * authUrl: 'https://auth.example.com',
10726
+ * redirectUrl: 'https://app.example.com',
10727
+ * });
10728
+ * ```
10729
+ */
10730
+ function handleLogout(options) {
10731
+ const { redirectUrl = window.location.origin, authUrl, tenantStorageKey = "tenant", logoutTimestampCookie = "ibl_logout_timestamp", callback, } = options;
10732
+ const tenant = window.localStorage.getItem(tenantStorageKey);
10733
+ window.localStorage.clear();
10734
+ if (tenant) {
10735
+ window.localStorage.setItem(tenantStorageKey, tenant);
10736
+ }
10737
+ // Set logout timestamp cookie to trigger logout on other SPAs
10738
+ setCookieForAuth(logoutTimestampCookie, Date.now().toString());
10739
+ clearCookies();
10740
+ callback === null || callback === void 0 ? void 0 : callback();
10741
+ if (!isInIframe()) {
10742
+ window.location.href = `${authUrl}/logout?redirect-to=${redirectUrl}${tenant ? "&tenant=" + tenant : ""}`;
10743
+ }
10744
+ }
10745
+
10328
10746
  const useExternalPricingPlan = ({ pricingModalData, userEmail, }) => {
10329
10747
  const pricingBoxIframeRef = React.useRef(null);
10330
10748
  const getIFrameReadyData = async () => {
@@ -10456,6 +10874,8 @@ function jwtDecode(token, options) {
10456
10874
  * - Polls for cookie changes every 2 seconds
10457
10875
  * - Refreshes the page when cross-SPA changes are detected
10458
10876
  * - Listens for storage events to update cookies when localStorage changes
10877
+ * - Monitors logout timestamp cookie to trigger cross-SPA logout
10878
+ * - Automatically logs out when another SPA initiates logout
10459
10879
  *
10460
10880
  * For React Native:
10461
10881
  * - Relies on AsyncStorage only (handled by StorageService)
@@ -10465,7 +10885,7 @@ function jwtDecode(token, options) {
10465
10885
  /**
10466
10886
  * Check if we're running in a web browser environment
10467
10887
  */
10468
- const isWeb = () => {
10888
+ const isWeb$1 = () => {
10469
10889
  return typeof window !== "undefined" && typeof document !== "undefined";
10470
10890
  };
10471
10891
  /**
@@ -10475,6 +10895,7 @@ const COOKIE_KEYS = {
10475
10895
  CURRENT_TENANT: "ibl_current_tenant",
10476
10896
  USER_DATA: "ibl_user_data",
10477
10897
  TENANT: "ibl_tenant",
10898
+ LOGOUT_TIMESTAMP: "ibl_logout_timestamp",
10478
10899
  };
10479
10900
  /**
10480
10901
  * Get the base domain for cookie sharing
@@ -10485,7 +10906,7 @@ const COOKIE_KEYS = {
10485
10906
  */
10486
10907
  const getBaseDomain = () => {
10487
10908
  // Must check for window existence before accessing it
10488
- if (!isWeb())
10909
+ if (!isWeb$1())
10489
10910
  return "";
10490
10911
  const hostname = window.location.hostname;
10491
10912
  // For localhost or IP addresses, use as-is
@@ -10514,7 +10935,7 @@ const CookieUtils = {
10514
10935
  * Uses SameSite=None for cross-subdomain sharing and base domain
10515
10936
  */
10516
10937
  set(name, value, days = 365) {
10517
- if (!isWeb())
10938
+ if (!isWeb$1())
10518
10939
  return;
10519
10940
  const expires = new Date();
10520
10941
  expires.setTime(expires.getTime() + days * 24 * 60 * 60 * 1000);
@@ -10526,7 +10947,7 @@ const CookieUtils = {
10526
10947
  * Get a cookie value by name
10527
10948
  */
10528
10949
  get(name) {
10529
- if (!isWeb())
10950
+ if (!isWeb$1())
10530
10951
  return null;
10531
10952
  const nameEQ = name + "=";
10532
10953
  const cookies = document.cookie.split(";");
@@ -10545,7 +10966,7 @@ const CookieUtils = {
10545
10966
  * Uses same domain logic as set() to ensure proper deletion
10546
10967
  */
10547
10968
  delete(name) {
10548
- if (!isWeb())
10969
+ if (!isWeb$1())
10549
10970
  return;
10550
10971
  const baseDomain = getBaseDomain();
10551
10972
  const domainAttr = baseDomain ? `;domain=${baseDomain}` : "";
@@ -10558,8 +10979,7 @@ const CookieUtils = {
10558
10979
  * On React Native, this is a no-op
10559
10980
  */
10560
10981
  async function syncAuthToCookies(storageService) {
10561
- console.log("##################### syncing auth to cookie");
10562
- if (!isWeb())
10982
+ if (!isWeb$1())
10563
10983
  return;
10564
10984
  try {
10565
10985
  const currentTenant = await storageService.getItem(LOCAL_STORAGE_KEYS.CURRENT_TENANT);
@@ -10588,13 +11008,23 @@ async function syncAuthToCookies(storageService) {
10588
11008
  console.error("[syncAuthToCookies] Error syncing to cookies:", error);
10589
11009
  }
10590
11010
  }
11011
+ /**
11012
+ * Clear current tenant cookie only (web only)
11013
+ * Should be called before tenant switching
11014
+ * On React Native, this is a no-op
11015
+ */
11016
+ function clearCurrentTenantCookie() {
11017
+ if (!isWeb$1())
11018
+ return;
11019
+ CookieUtils.delete(COOKIE_KEYS.CURRENT_TENANT);
11020
+ }
10591
11021
  /**
10592
11022
  * Clear all authentication cookies (web only)
10593
11023
  * Should be called on logout
10594
11024
  * On React Native, this is a no-op
10595
11025
  */
10596
11026
  function clearAuthCookies() {
10597
- if (!isWeb())
11027
+ if (!isWeb$1())
10598
11028
  return;
10599
11029
  CookieUtils.delete(COOKIE_KEYS.CURRENT_TENANT);
10600
11030
  CookieUtils.delete(COOKIE_KEYS.USER_DATA);
@@ -10606,14 +11036,30 @@ function clearAuthCookies() {
10606
11036
  * On React Native, always returns false (no-op)
10607
11037
  */
10608
11038
  async function syncCookiesToLocalStorage(storageService) {
10609
- if (!isWeb())
11039
+ if (!isWeb$1())
10610
11040
  return false;
10611
11041
  try {
10612
11042
  let needsRefresh = false;
10613
11043
  // Check current_tenant
10614
11044
  const cookieCurrentTenant = CookieUtils.get(COOKIE_KEYS.CURRENT_TENANT);
11045
+ console.log("[syncCookiesToLocalStorage] cookieCurrentTenant", cookieCurrentTenant);
10615
11046
  const localCurrentTenant = await storageService.getItem(LOCAL_STORAGE_KEYS.CURRENT_TENANT);
10616
- if (cookieCurrentTenant !== localCurrentTenant) {
11047
+ console.log("[syncCookiesToLocalStorage] localCurrentTenant", localCurrentTenant);
11048
+ // Compare current tenant objects by key field only to avoid false positives from extra fields
11049
+ let currentTenantIsDifferent = false;
11050
+ if (cookieCurrentTenant && localCurrentTenant) {
11051
+ try {
11052
+ const cookieTenant = JSON.parse(cookieCurrentTenant);
11053
+ const localTenant = JSON.parse(localCurrentTenant);
11054
+ // Compare by the tenant key only
11055
+ currentTenantIsDifferent = cookieTenant.key !== localTenant.key;
11056
+ }
11057
+ catch (e) {
11058
+ // If parsing fails, fall back to string comparison
11059
+ currentTenantIsDifferent = cookieCurrentTenant !== localCurrentTenant;
11060
+ }
11061
+ }
11062
+ if (currentTenantIsDifferent) {
10617
11063
  if (cookieCurrentTenant) {
10618
11064
  await storageService.setItem(LOCAL_STORAGE_KEYS.CURRENT_TENANT, cookieCurrentTenant);
10619
11065
  }
@@ -10625,8 +11071,24 @@ async function syncCookiesToLocalStorage(storageService) {
10625
11071
  }
10626
11072
  // Check userData
10627
11073
  const cookieUserData = CookieUtils.get(COOKIE_KEYS.USER_DATA);
11074
+ console.log("[syncCookiesToLocalStorage] cookieUserData", cookieUserData);
10628
11075
  const localUserData = await storageService.getItem(LOCAL_STORAGE_KEYS.USER_DATA);
10629
- if (cookieUserData !== localUserData) {
11076
+ console.log("[syncCookiesToLocalStorage] localUserData", localUserData);
11077
+ // Compare userData objects by user_id to avoid false positives from extra fields
11078
+ let userDataIsDifferent = false;
11079
+ if (cookieUserData && localUserData) {
11080
+ try {
11081
+ const cookieUser = JSON.parse(cookieUserData);
11082
+ const localUser = JSON.parse(localUserData);
11083
+ // Compare by user_id - the primary identifier
11084
+ userDataIsDifferent = cookieUser.user_id !== localUser.user_id;
11085
+ }
11086
+ catch (e) {
11087
+ // If parsing fails, fall back to string comparison
11088
+ userDataIsDifferent = cookieUserData !== localUserData;
11089
+ }
11090
+ }
11091
+ if (userDataIsDifferent) {
10630
11092
  if (cookieUserData) {
10631
11093
  await storageService.setItem(LOCAL_STORAGE_KEYS.USER_DATA, cookieUserData);
10632
11094
  }
@@ -10638,8 +11100,37 @@ async function syncCookiesToLocalStorage(storageService) {
10638
11100
  }
10639
11101
  // Check tenant
10640
11102
  const cookieTenant = CookieUtils.get(COOKIE_KEYS.TENANT);
11103
+ console.log("[syncCookiesToLocalStorage] cookieTenant", cookieTenant);
10641
11104
  const localTenant = await storageService.getItem(LOCAL_STORAGE_KEYS.TENANTS);
10642
- if (cookieTenant !== localTenant) {
11105
+ console.log("[syncCookiesToLocalStorage] localTenant", localTenant);
11106
+ // Compare tenant arrays by checking length and tenant keys
11107
+ let tenantsAreDifferent = false;
11108
+ if (cookieTenant &&
11109
+ localTenant &&
11110
+ cookieTenant !== "[]" &&
11111
+ localTenant !== "[]") {
11112
+ try {
11113
+ const cookieTenantsArray = JSON.parse(cookieTenant);
11114
+ const localTenantsArray = JSON.parse(localTenant);
11115
+ // Check if arrays have same length
11116
+ if (cookieTenantsArray.length !== localTenantsArray.length) {
11117
+ tenantsAreDifferent = true;
11118
+ }
11119
+ else {
11120
+ // Check if all tenant keys match
11121
+ const cookieKeys = new Set(cookieTenantsArray.map((t) => t.key));
11122
+ const localKeys = new Set(localTenantsArray.map((t) => t.key));
11123
+ tenantsAreDifferent =
11124
+ cookieKeys.size !== localKeys.size ||
11125
+ [...cookieKeys].some((key) => !localKeys.has(key));
11126
+ }
11127
+ }
11128
+ catch (e) {
11129
+ // If parsing fails, fall back to string comparison
11130
+ tenantsAreDifferent = cookieTenant !== localTenant;
11131
+ }
11132
+ }
11133
+ if (tenantsAreDifferent) {
10643
11134
  if (cookieTenant) {
10644
11135
  await storageService.setItem(LOCAL_STORAGE_KEYS.TENANTS, cookieTenant);
10645
11136
  }
@@ -10694,6 +11185,7 @@ async function isJwtTokenExpired(storageService) {
10694
11185
  async function validateJwtToken(storageService) {
10695
11186
  try {
10696
11187
  const edxJwtToken = await storageService.getItem(LOCAL_STORAGE_KEYS.EDX_TOKEN_KEY);
11188
+ console.log("[AuthProvider] JWT token ", edxJwtToken);
10697
11189
  const userData = await storageService.getItem(LOCAL_STORAGE_KEYS.USER_DATA);
10698
11190
  if (!edxJwtToken || !userData) {
10699
11191
  return false;
@@ -10716,7 +11208,9 @@ async function validateJwtToken(storageService) {
10716
11208
  function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure, redirectToAuthSpa, hasNonExpiredAuthToken, username, pathname, storageService, skipAuthCheck, token, }) {
10717
11209
  const [isAuthenticating, setIsAuthenticating] = React.useState(true);
10718
11210
  const [userIsAccessingPublicRoute, setUserIsAccessingPublicRoute] = React.useState(false);
11211
+ const [initialSyncComplete, setInitialSyncComplete] = React.useState(false);
10719
11212
  const cookieCheckIntervalRef = React.useRef(null);
11213
+ const lastLogoutTimestampRef = React.useRef(null);
10720
11214
  // RTK Query hook for refreshing JWT token
10721
11215
  const [refreshJwtToken] = useLazyRefreshJwtTokenQuery();
10722
11216
  /**
@@ -10725,24 +11219,65 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
10725
11219
  * On React Native, this is a no-op
10726
11220
  */
10727
11221
  React.useEffect(() => {
10728
- console.log("################******* useEffect sync auth");
10729
- if (!storageService || !isWeb())
11222
+ if (!storageService || !isWeb$1()) {
11223
+ // If no storage service or not web, mark sync as complete immediately
11224
+ setInitialSyncComplete(true);
10730
11225
  return;
11226
+ }
10731
11227
  // Initial sync on mount
10732
11228
  async function initialSync() {
10733
- const needsRefresh = await syncCookiesToLocalStorage(storageService);
10734
- if (needsRefresh) {
10735
- console.log("[AuthProvider] Cookie sync detected changes, refreshing page...");
10736
- window.location.reload();
11229
+ try {
11230
+ // Initialize last known logout timestamp
11231
+ lastLogoutTimestampRef.current = CookieUtils.get(COOKIE_KEYS.LOGOUT_TIMESTAMP);
11232
+ const needsRefresh = await syncCookiesToLocalStorage(storageService);
11233
+ if (needsRefresh) {
11234
+ console.log("[auth-redirect] Cookie sync detected changes, refreshing page");
11235
+ redirectToAuthSpa(undefined, undefined, false, false);
11236
+ }
11237
+ else {
11238
+ await syncAuthToCookies(storageService);
11239
+ }
11240
+ }
11241
+ finally {
11242
+ // Mark initial sync as complete
11243
+ setInitialSyncComplete(true);
10737
11244
  }
10738
11245
  }
10739
11246
  initialSync();
10740
11247
  // Poll for cookie changes every 2 seconds to detect cross-SPA updates
10741
11248
  cookieCheckIntervalRef.current = setInterval(async () => {
11249
+ // Skip cookie sync checks if user is completing SSO at /sso-login
11250
+ const completingSso = new RegExp("^\/sso-login").test(pathname);
11251
+ if (completingSso) {
11252
+ console.log("[AuthProvider] Skipping cookie sync check for public route");
11253
+ return;
11254
+ }
11255
+ // Check for logout timestamp changes (cross-SPA logout detection)
11256
+ const currentLogoutTimestamp = CookieUtils.get(COOKIE_KEYS.LOGOUT_TIMESTAMP);
11257
+ if (currentLogoutTimestamp &&
11258
+ lastLogoutTimestampRef.current &&
11259
+ currentLogoutTimestamp !== lastLogoutTimestampRef.current) {
11260
+ console.log("[auth-redirect] Logout detected from another SPA", {
11261
+ previousTimestamp: lastLogoutTimestampRef.current,
11262
+ newTimestamp: currentLogoutTimestamp,
11263
+ });
11264
+ lastLogoutTimestampRef.current = currentLogoutTimestamp;
11265
+ redirectToAuthSpa(undefined, undefined, true);
11266
+ return;
11267
+ }
10742
11268
  const needsRefresh = await syncCookiesToLocalStorage(storageService);
10743
11269
  if (needsRefresh) {
10744
- console.log("[AuthProvider] Cookie sync detected changes from another SPA, refreshing page...");
10745
- window.location.reload();
11270
+ console.log("[auth-redirect] Cookie sync detected changes from another SPA, refreshing page");
11271
+ let cookieTenantKey;
11272
+ try {
11273
+ const cookieCurrentTenant = JSON.parse(CookieUtils.get(COOKIE_KEYS.CURRENT_TENANT));
11274
+ cookieTenantKey = cookieCurrentTenant.key;
11275
+ }
11276
+ catch (_a) { }
11277
+ redirectToAuthSpa(undefined, cookieTenantKey, false, false);
11278
+ }
11279
+ else {
11280
+ await syncAuthToCookies(storageService);
10746
11281
  }
10747
11282
  }, 2000);
10748
11283
  // Cleanup interval on unmount
@@ -10751,15 +11286,14 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
10751
11286
  clearInterval(cookieCheckIntervalRef.current);
10752
11287
  }
10753
11288
  };
10754
- }, [storageService]);
11289
+ }, [storageService, middleware, pathname]);
10755
11290
  /**
10756
11291
  * Listen for storage events from other tabs/windows (web only)
10757
11292
  * This catches same-SPA changes in different tabs
10758
11293
  * On React Native, this is a no-op
10759
11294
  */
10760
11295
  React.useEffect(() => {
10761
- console.log("################ useEffect sync auth");
10762
- if (!storageService || !isWeb())
11296
+ if (!storageService || !isWeb$1())
10763
11297
  return;
10764
11298
  const handleStorageChange = async (event) => {
10765
11299
  // Only handle changes to our auth-related keys
@@ -10790,14 +11324,15 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
10790
11324
  if (!hasNonExpiredAuthToken()) {
10791
11325
  const reason = "Auth token expired";
10792
11326
  onAuthFailure === null || onAuthFailure === void 0 ? void 0 : onAuthFailure(reason);
10793
- redirectToAuthSpa();
11327
+ console.log("[auth-redirect] Auth token expired");
11328
+ redirectToAuthSpa(undefined, undefined, true);
10794
11329
  return;
10795
11330
  }
10796
11331
  // Check JWT token expiry and force logout for protected routes
10797
11332
  if (isProtectedRoute && storageService) {
10798
11333
  const jwtExpired = await isJwtTokenExpired(storageService);
10799
11334
  if (jwtExpired) {
10800
- console.log("[AuthProvider] JWT token has expired, forcing logout...");
11335
+ console.log("[auth-redirect] JWT token has expired, forcing logout");
10801
11336
  // Clear all auth-related storage keys
10802
11337
  clearAuthCookies();
10803
11338
  const reason = "JWT token expired";
@@ -10819,11 +11354,18 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
10819
11354
  console.log("[AuthProvider] JWT token refreshed successfully");
10820
11355
  }
10821
11356
  else if (result.error) {
10822
- console.error("[AuthProvider] Failed to refresh JWT token:", result.error);
11357
+ console.log("[auth-redirect] Failed to refresh JWT token", {
11358
+ error: result.error,
11359
+ });
11360
+ redirectToAuthSpa(undefined, undefined, true);
11361
+ return;
10823
11362
  }
10824
11363
  }
10825
11364
  catch (refreshError) {
10826
- console.error("[AuthProvider] Failed to refresh JWT token:", refreshError);
11365
+ console.log("[auth-redirect] JWT token refresh error", {
11366
+ error: refreshError,
11367
+ });
11368
+ redirectToAuthSpa(undefined, undefined, true);
10827
11369
  // Continue with auth check even if JWT refresh fails
10828
11370
  }
10829
11371
  }
@@ -10835,12 +11377,18 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
10835
11377
  setIsAuthenticating(false);
10836
11378
  }
10837
11379
  catch (error) {
11380
+ console.error("[AuthProvider] Error performing auth check:", error);
10838
11381
  const errorMessage = error instanceof Error ? error.message : String(error);
10839
11382
  onAuthFailure === null || onAuthFailure === void 0 ? void 0 : onAuthFailure(`Unexpected error: ${errorMessage}`);
10840
11383
  redirectToAuthSpa();
10841
11384
  }
10842
11385
  }
10843
11386
  React.useEffect(() => {
11387
+ // Wait for initial sync to complete before performing auth check
11388
+ if (!initialSyncComplete) {
11389
+ console.log("[useAuthProvider] Waiting for initial sync to complete...");
11390
+ return;
11391
+ }
10844
11392
  async function checkAuth() {
10845
11393
  setIsAuthenticating(true);
10846
11394
  const authRequired = (await determineAuthRequired(middleware, pathname)) && !token;
@@ -10861,7 +11409,7 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
10861
11409
  }
10862
11410
  console.log("[useAuthProvider] performing auth check for ", username);
10863
11411
  checkAuth();
10864
- }, [username]);
11412
+ }, [username, initialSyncComplete]);
10865
11413
  return {
10866
11414
  isAuthenticating,
10867
11415
  userIsAccessingPublicRoute,
@@ -10929,7 +11477,7 @@ function AuthProvider({ children, fallback, middleware = new Map(), onAuthSucces
10929
11477
  if (isAuthenticating) {
10930
11478
  return fallback;
10931
11479
  }
10932
- return (jsxRuntime.jsx(AuthContextProvider, { value: { userIsAccessingPublicRoute, setUserIsAccessingPublicRoute }, children: jsxRuntime.jsx(jsxRuntime.Fragment, {}) }));
11480
+ return (jsxRuntime.jsx(AuthContextProvider, { value: { userIsAccessingPublicRoute, setUserIsAccessingPublicRoute }, children: children }));
10933
11481
  }
10934
11482
 
10935
11483
  /**
@@ -10942,6 +11490,12 @@ function AuthProvider({ children, fallback, middleware = new Map(), onAuthSucces
10942
11490
  * - Tenant metadata retrieval
10943
11491
  * - User-tenant relationship verification
10944
11492
  */
11493
+ /**
11494
+ * Check if we're running in a web browser environment
11495
+ */
11496
+ const isWeb = () => {
11497
+ return typeof window !== "undefined" && typeof document !== "undefined";
11498
+ };
10945
11499
  const TenantContext = React.createContext(undefined);
10946
11500
  /**
10947
11501
  * Context Provider component that wraps children with tenant context
@@ -10962,7 +11516,7 @@ const useTenantContext = () => React.useContext(TenantContext);
10962
11516
  * 4. Handles tenant-specific domain redirects
10963
11517
  * 5. Maintains tenant access state
10964
11518
  */
10965
- function TenantProvider({ children, fallback, onAuthSuccess, onAuthFailure, currentTenant, requestedTenant, saveCurrentTenant, saveUserTenants, handleTenantSwitch, saveVisitingTenant, removeVisitingTenant, saveUserTokens, saveTenant, onAutoJoinUserToTenant, }) {
11519
+ function TenantProvider({ children, fallback, onAuthSuccess, onAuthFailure, currentTenant, requestedTenant, saveCurrentTenant, saveUserTenants, handleTenantSwitch, saveVisitingTenant, removeVisitingTenant, saveUserTokens, saveTenant, onAutoJoinUserToTenant, redirectToAuthSpa, username, }) {
10966
11520
  const { userIsAccessingPublicRoute, setUserIsAccessingPublicRoute } = useAuthContext();
10967
11521
  const [determineUserPath, setDetermineUserPath] = React.useState(false);
10968
11522
  const [isLoading, setIsLoading] = React.useState(true);
@@ -10973,6 +11527,26 @@ function TenantProvider({ children, fallback, onAuthSuccess, onAuthFailure, curr
10973
11527
  const [getAppToken] = useGetAppTokensMutation();
10974
11528
  const [tenantKey, setTenantKey] = React.useState(currentTenant);
10975
11529
  const [metadata, setMetadata] = React.useState({});
11530
+ // Fetch custom domain to get platform_key
11531
+ const currentDomain = typeof window !== "undefined" ? window.location.hostname : "";
11532
+ const { data: customDomainData, isLoading: isLoadingCustomDomain, isError: isCustomDomainError, } = useGetCustomDomainsQuery({ params: { domain: currentDomain } }, { skip: !isWeb() || !currentDomain });
11533
+ // Extract platform_key from custom domain response to use as requestedTenant
11534
+ const customDomainPlatformKey = React.useMemo(() => {
11535
+ if (customDomainData &&
11536
+ typeof customDomainData === "object" &&
11537
+ "custom_domains" in customDomainData) {
11538
+ const domains = customDomainData.custom_domains;
11539
+ if (Array.isArray(domains) &&
11540
+ domains.length > 0 &&
11541
+ domains[0].platform_key) {
11542
+ console.log("[TenantProvider] Using platform_key from custom domain:", domains[0].platform_key);
11543
+ return domains[0].platform_key;
11544
+ }
11545
+ }
11546
+ return undefined;
11547
+ }, [customDomainData]);
11548
+ // Use custom domain platform_key as requested tenant if available, otherwise use provided requestedTenant
11549
+ const effectiveRequestedTenant = customDomainPlatformKey || requestedTenant;
10976
11550
  /**
10977
11551
  * Helper function to enhance tenants with platform metadata from user apps
10978
11552
  */
@@ -11032,24 +11606,32 @@ function TenantProvider({ children, fallback, onAuthSuccess, onAuthFailure, curr
11032
11606
  const otherTenant = tenants.find((t) => t.key !== MAIN_TENANT_KEY);
11033
11607
  if (mainTenant &&
11034
11608
  otherTenant &&
11035
- requestedTenant &&
11036
- requestedTenant !== otherTenant.key) {
11609
+ effectiveRequestedTenant &&
11610
+ effectiveRequestedTenant !== otherTenant.key) {
11037
11611
  handleTenantSwitch(otherTenant.key, true);
11038
11612
  console.log("TenantProvider: Triggering tenant switch to newly joined tenant:", otherTenant.key);
11039
11613
  }
11040
11614
  }
11041
- // Enhance tenants with platform metadata
11615
+ // Enhance tenants with platform metadatax
11042
11616
  let enhancedTenants = await enhanceTenants(tenants);
11617
+ // if there is customDomainPlatformKey and user doesn't belong to that tenant, trigger logout
11618
+ if (customDomainPlatformKey) {
11619
+ if (!(enhancedTenants === null || enhancedTenants === void 0 ? void 0 : enhancedTenants.find((tenant) => tenant.key === customDomainPlatformKey))) {
11620
+ redirectToAuthSpa === null || redirectToAuthSpa === void 0 ? void 0 : redirectToAuthSpa(undefined, undefined, true);
11621
+ return;
11622
+ }
11623
+ }
11043
11624
  saveUserTenants(enhancedTenants);
11044
11625
  // Find requested tenant or fallback to current tenant
11045
- console.log("checking requested tenant", { requestedTenant });
11046
- let tenant = enhancedTenants === null || enhancedTenants === void 0 ? void 0 : enhancedTenants.find((tenant) => tenant.key === requestedTenant);
11047
- console.log("requested tenant", { tenant });
11626
+ console.log("checking requested tenant", JSON.stringify({
11627
+ requestedTenant: effectiveRequestedTenant,
11628
+ customDomainPlatformKey,
11629
+ }));
11630
+ let tenant = enhancedTenants === null || enhancedTenants === void 0 ? void 0 : enhancedTenants.find((tenant) => tenant.key === effectiveRequestedTenant);
11631
+ console.log("requested tenant", tenant);
11048
11632
  if (!tenant && !userIsAccessingPublicRoute) {
11049
11633
  setDetermineUserPath(true);
11050
- console.log("no requested tenant, checking current tenant", {
11051
- currentTenant,
11052
- });
11634
+ console.log("no requested tenant, checking current tenant", currentTenant);
11053
11635
  tenant = enhancedTenants === null || enhancedTenants === void 0 ? void 0 : enhancedTenants.find((tenant) => tenant.key === currentTenant);
11054
11636
  console.log("current tenant", { tenant });
11055
11637
  }
@@ -11061,7 +11643,7 @@ function TenantProvider({ children, fallback, onAuthSuccess, onAuthFailure, curr
11061
11643
  tenant = enhancedTenants[0];
11062
11644
  }
11063
11645
  // Fetch and validate tenant metadata
11064
- console.log("fetching tenant metadata", { tenant });
11646
+ console.log("fetching tenant metadata", JSON.stringify(tenant));
11065
11647
  const { data: tenantMetadata } = await fetchTenantMetadata([
11066
11648
  {
11067
11649
  org: (tenant === null || tenant === void 0 ? void 0 : tenant.key) || currentTenant,
@@ -11132,6 +11714,11 @@ function TenantProvider({ children, fallback, onAuthSuccess, onAuthFailure, curr
11132
11714
  platform_name: data.platform_name,
11133
11715
  is_advertising: (_a = data.metadata) === null || _a === void 0 ? void 0 : _a.is_advertising,
11134
11716
  };
11717
+ if (!username) {
11718
+ saveVisitingTenant === null || saveVisitingTenant === void 0 ? void 0 : saveVisitingTenant(newCurrentTenant);
11719
+ // user is not authenticated so we don't need to do anything that concerns an authenticated user
11720
+ return;
11721
+ }
11135
11722
  const { data: tenants } = await fetchUserTenants();
11136
11723
  const enhancedTenants = await enhanceTenants(tenants, data);
11137
11724
  saveUserTenants(enhancedTenants);
@@ -11203,28 +11790,44 @@ function TenantProvider({ children, fallback, onAuthSuccess, onAuthFailure, curr
11203
11790
  }
11204
11791
  // Effect to handle tenant determination when auth state changes
11205
11792
  React.useEffect(() => {
11793
+ // Wait for custom domain query to complete (unless skipped or error)
11794
+ const customDomainQuerySkipped = !isWeb() || !currentDomain;
11795
+ if (!customDomainQuerySkipped && isLoadingCustomDomain) {
11796
+ console.log("[TenantProvider] Waiting for custom domain query to complete...");
11797
+ return;
11798
+ }
11799
+ if (isCustomDomainError) {
11800
+ console.warn("[TenantProvider] Custom domain query failed, proceeding without custom domain platform_key");
11801
+ }
11206
11802
  // NOTE: currentTenant comes from local storage.
11207
11803
  // it's the tenant the user is currently signed into.
11208
11804
  console.log("determineWhichTenantToUse", {
11209
11805
  userIsAccessingPublicRoute,
11210
11806
  currentTenant,
11211
11807
  requestedTenant,
11808
+ effectiveRequestedTenant,
11809
+ customDomainPlatformKey,
11212
11810
  });
11213
- if (userIsAccessingPublicRoute && requestedTenant.length === 0) {
11811
+ if (userIsAccessingPublicRoute && effectiveRequestedTenant.length === 0) {
11214
11812
  setIsLoading(false);
11215
11813
  return;
11216
11814
  }
11217
- if (userIsAccessingPublicRoute && requestedTenant.length > 0) {
11815
+ if (userIsAccessingPublicRoute && effectiveRequestedTenant.length > 0) {
11218
11816
  setIsLoading(true);
11219
- setTenantKey(requestedTenant);
11220
- handleLoadTenantMetadata(requestedTenant);
11817
+ setTenantKey(effectiveRequestedTenant);
11818
+ handleLoadTenantMetadata(effectiveRequestedTenant);
11221
11819
  }
11222
11820
  else {
11223
11821
  setIsLoading(true);
11224
11822
  removeVisitingTenant === null || removeVisitingTenant === void 0 ? void 0 : removeVisitingTenant();
11225
11823
  determineWhichTenantToUse();
11226
11824
  }
11227
- }, [userIsAccessingPublicRoute, requestedTenant]);
11825
+ }, [
11826
+ userIsAccessingPublicRoute,
11827
+ effectiveRequestedTenant,
11828
+ isLoadingCustomDomain,
11829
+ isCustomDomainError,
11830
+ ]);
11228
11831
  // Show fallback component during tenant determination
11229
11832
  if (isLoading) {
11230
11833
  return fallback;
@@ -11257,24 +11860,17 @@ function TenantProvider({ children, fallback, onAuthSuccess, onAuthFailure, curr
11257
11860
  * 3. Manages redirection based on mentor availability
11258
11861
  * 4. Integrates with tenant context for access control
11259
11862
  */
11260
- function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redirectToAuthSpa, redirectToMentor, onLoadMentorsPermissions, redirectToNoMentorsPage, redirectToCreateMentor, username, isAdmin, mainTenantKey, requestedMentorId, handleMentorNotFound, forceDetermineMentor = false, }) {
11863
+ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redirectToAuthSpa, redirectToMentor, onLoadMentorsPermissions, redirectToNoMentorsPage, redirectToCreateMentor, username, isAdmin, mainTenantKey, requestedMentorId, handleMentorNotFound, forceDetermineMentor = false, onComplete, }) {
11261
11864
  const [isLoading, setIsLoading] = React.useState(true);
11262
11865
  const { userIsAccessingPublicRoute } = useAuthContext();
11263
- const { determineUserPath, tenantKey } = useTenantContext();
11866
+ const { determineUserPath, tenantKey, metadata } = useTenantContext();
11264
11867
  const isMainTenant = tenantKey === mainTenantKey;
11265
- console.log("MentorProvider initialized", {
11266
- username,
11267
- isAdmin,
11268
- tenantKey,
11269
- mainTenantKey,
11270
- isMainTenant,
11271
- requestedMentorId,
11272
- determineUserPath,
11273
- });
11868
+ console.log("MentorProvider initialized", username, isAdmin, tenantKey, mainTenantKey, isMainTenant, requestedMentorId, determineUserPath);
11274
11869
  const [fetchMentors] = useLazyGetMentorsQuery();
11275
11870
  const [fetchSeedMentors] = useLazySeedMentorsQuery();
11276
11871
  const [getMentorPublicSettings] = useLazyGetMentorPublicSettingsQuery();
11277
11872
  const [getRbacPermissions] = useGetRbacPermissionsMutation();
11873
+ const [getRecentlyAccessedMentors] = useLazyGetRecentlyAccessedMentorsQuery();
11278
11874
  const QUERY_LIMIT = 10;
11279
11875
  const loadMentorsPermissions = async (mentorDbId) => {
11280
11876
  try {
@@ -11291,6 +11887,33 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
11291
11887
  }
11292
11888
  catch (_a) { }
11293
11889
  };
11890
+ /**
11891
+ * Gets the mentor database ID from public settings if not available on the mentor object
11892
+ */
11893
+ const getMentorDbId = async (mentor) => {
11894
+ if (mentor === null || mentor === void 0 ? void 0 : mentor.id) {
11895
+ return mentor.id;
11896
+ }
11897
+ if (mentor === null || mentor === void 0 ? void 0 : mentor.unique_id) {
11898
+ try {
11899
+ const response = await getMentorPublicSettings({
11900
+ // @ts-ignore
11901
+ mentor: mentor.unique_id,
11902
+ org: tenantKey,
11903
+ // @ts-ignore
11904
+ userId: username,
11905
+ }).unwrap();
11906
+ return response === null || response === void 0 ? void 0 : response.mentor_id;
11907
+ }
11908
+ catch (error) {
11909
+ console.log("failed to fetch mentor ID from public settings", {
11910
+ error: error instanceof Error ? error.message : String(error),
11911
+ mentorUniqueId: mentor.unique_id,
11912
+ });
11913
+ }
11914
+ }
11915
+ return undefined;
11916
+ };
11294
11917
  /**
11295
11918
  * Determines which mentor to redirect the user to by following this priority:
11296
11919
  * 1. Recently accessed mentors
@@ -11298,24 +11921,60 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
11298
11921
  * 3. Non-featured mentors
11299
11922
  * 4. Seeded mentors (for admin users)
11300
11923
  * 5. Creation flow or no mentors page
11924
+ *
11925
+ * Returns the mentor object if found, undefined otherwise
11301
11926
  */
11302
11927
  async function determineMentorToRedirectTo() {
11303
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
11304
- console.log("starting mentor determination process", {
11928
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
11929
+ console.log("starting mentor determination process", JSON.stringify({
11305
11930
  tenantKey,
11306
11931
  username,
11307
11932
  isAdmin,
11308
11933
  isMainTenant,
11309
- });
11934
+ }));
11935
+ console.log("###################### metadata is ", metadata, typeof metadata);
11310
11936
  setIsLoading(true);
11311
11937
  try {
11312
11938
  // Get the user's recent mentors
11313
- console.log("fetching recent mentors", {
11939
+ console.log("fetching recent mentors", JSON.stringify({
11314
11940
  tenantKey,
11315
11941
  username,
11316
11942
  limit: QUERY_LIMIT,
11317
11943
  orderBy: "recently_accessed_at",
11944
+ }));
11945
+ if (typeof metadata === "object" &&
11946
+ metadata.skills_embedded_mentor_name) {
11947
+ const defaultMentor = JSON.parse(metadata.skills_embedded_mentor_name);
11948
+ if (defaultMentor === null || defaultMentor === void 0 ? void 0 : defaultMentor.unique_id) {
11949
+ return defaultMentor;
11950
+ }
11951
+ }
11952
+ // Check for recently accessed mentors (second choice)
11953
+ console.log("checking recently accessed mentors", JSON.stringify({
11954
+ tenantKey,
11955
+ username,
11956
+ }));
11957
+ const recentlyAccessedResult = await getRecentlyAccessedMentors({
11958
+ org: tenantKey,
11959
+ // @ts-ignore
11960
+ userId: username,
11318
11961
  });
11962
+ // @ts-ignore
11963
+ const recentlyAccessedMentors = recentlyAccessedResult.data;
11964
+ const starredMentors = recentlyAccessedMentors === null || recentlyAccessedMentors === void 0 ? void 0 : recentlyAccessedMentors.starred_mentors;
11965
+ let recentMentors = recentlyAccessedMentors === null || recentlyAccessedMentors === void 0 ? void 0 : recentlyAccessedMentors.recent_mentors;
11966
+ if (starredMentors.length > 0) {
11967
+ const starredMentor = starredMentors[0];
11968
+ if (starredMentor === null || starredMentor === void 0 ? void 0 : starredMentor.unique_id) {
11969
+ return starredMentor;
11970
+ }
11971
+ }
11972
+ if (recentMentors.length > 0) {
11973
+ const recentMentor = recentMentors[0];
11974
+ if (recentMentor === null || recentMentor === void 0 ? void 0 : recentMentor.unique_id) {
11975
+ return recentMentor;
11976
+ }
11977
+ }
11319
11978
  const recentMentorsResult = await fetchMentors({
11320
11979
  // @ts-ignore
11321
11980
  org: tenantKey,
@@ -11323,26 +11982,19 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
11323
11982
  limit: QUERY_LIMIT,
11324
11983
  orderBy: "recently_accessed_at",
11325
11984
  });
11326
- const recentMentors = ((_a = recentMentorsResult.data) === null || _a === void 0 ? void 0 : _a.results) || [];
11327
- console.log("recent mentors fetched", {
11985
+ recentMentors = ((_a = recentMentorsResult.data) === null || _a === void 0 ? void 0 : _a.results) || [];
11986
+ console.log("recent mentors fetched", JSON.stringify({
11328
11987
  count: recentMentors.length,
11329
11988
  mentorIds: recentMentors.map((m) => m === null || m === void 0 ? void 0 : m.unique_id),
11330
- });
11989
+ }));
11331
11990
  // Check if we found recent mentors for the tenant
11332
11991
  if (recentMentors.length > 0) {
11333
- const selectedMentorId = ((_b = recentMentors[0]) === null || _b === void 0 ? void 0 : _b.unique_id) || "";
11334
- const selectedMentorDbId = ((_c = recentMentors[0]) === null || _c === void 0 ? void 0 : _c.id) || "";
11335
- console.log("redirecting to recent mentor", {
11336
- selectedMentorId,
11337
- mentorName: (_d = recentMentors[0]) === null || _d === void 0 ? void 0 : _d.name,
11992
+ console.log("found recent mentor", JSON.stringify({
11993
+ selectedMentorId: (_b = recentMentors[0]) === null || _b === void 0 ? void 0 : _b.unique_id,
11994
+ mentorName: (_c = recentMentors[0]) === null || _c === void 0 ? void 0 : _c.name,
11338
11995
  tenantKey,
11339
- });
11340
- const rbacPermissions = await loadMentorsPermissions(selectedMentorDbId);
11341
- // Select the most recent mentor as current mentor
11342
- onLoadMentorsPermissions === null || onLoadMentorsPermissions === void 0 ? void 0 : onLoadMentorsPermissions(rbacPermissions);
11343
- redirectToMentor(tenantKey, selectedMentorId);
11344
- onAuthSuccess === null || onAuthSuccess === void 0 ? void 0 : onAuthSuccess();
11345
- return;
11996
+ }));
11997
+ return recentMentors[0];
11346
11998
  }
11347
11999
  // If no recent mentors, get featured mentors
11348
12000
  console.log("no recent mentors found, fetching featured mentors", {
@@ -11356,7 +12008,7 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
11356
12008
  limit: QUERY_LIMIT,
11357
12009
  orderBy: "recently_accessed_at",
11358
12010
  });
11359
- const featuredMentors = ((_e = featuredMentorsResult.data) === null || _e === void 0 ? void 0 : _e.results) || [];
12011
+ const featuredMentors = ((_d = featuredMentorsResult.data) === null || _d === void 0 ? void 0 : _d.results) || [];
11360
12012
  console.log("featured mentors fetched", {
11361
12013
  count: featuredMentors.length,
11362
12014
  mentorIds: featuredMentors.map((m) => m === null || m === void 0 ? void 0 : m.unique_id),
@@ -11376,16 +12028,11 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
11376
12028
  const defaultIblMentor = featuredMentors.find((mentor) => { var _a; return ((_a = mentor === null || mentor === void 0 ? void 0 : mentor.metadata) === null || _a === void 0 ? void 0 : _a.default) === true; });
11377
12029
  // Check if found default featured mentor
11378
12030
  if (defaultIblMentor) {
11379
- console.log("redirecting to default IBL mentor", {
12031
+ console.log("found default IBL mentor", {
11380
12032
  mentorId: defaultIblMentor === null || defaultIblMentor === void 0 ? void 0 : defaultIblMentor.unique_id,
11381
12033
  mentorName: defaultIblMentor === null || defaultIblMentor === void 0 ? void 0 : defaultIblMentor.name,
11382
12034
  });
11383
- const defaultIblMentorDbId = (defaultIblMentor === null || defaultIblMentor === void 0 ? void 0 : defaultIblMentor.id) || "";
11384
- const rbacPermissions = await loadMentorsPermissions(defaultIblMentorDbId);
11385
- onLoadMentorsPermissions === null || onLoadMentorsPermissions === void 0 ? void 0 : onLoadMentorsPermissions(rbacPermissions);
11386
- redirectToMentor === null || redirectToMentor === void 0 ? void 0 : redirectToMentor(tenantKey, (defaultIblMentor === null || defaultIblMentor === void 0 ? void 0 : defaultIblMentor.unique_id) || "");
11387
- onAuthSuccess === null || onAuthSuccess === void 0 ? void 0 : onAuthSuccess();
11388
- return;
12035
+ return defaultIblMentor;
11389
12036
  }
11390
12037
  }
11391
12038
  else {
@@ -11396,30 +12043,19 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
11396
12043
  // Check if there's a default featured mentor
11397
12044
  const defaultFeatureMentor = featuredMentors.find((mentor) => { var _a; return ((_a = mentor === null || mentor === void 0 ? void 0 : mentor.metadata) === null || _a === void 0 ? void 0 : _a.default) === true; });
11398
12045
  if (defaultFeatureMentor) {
11399
- console.log("redirecting to default featured mentor", {
12046
+ console.log("found default featured mentor", {
11400
12047
  mentorId: defaultFeatureMentor === null || defaultFeatureMentor === void 0 ? void 0 : defaultFeatureMentor.unique_id,
11401
12048
  mentorName: defaultFeatureMentor === null || defaultFeatureMentor === void 0 ? void 0 : defaultFeatureMentor.name,
11402
12049
  });
11403
- const defaultFeatureMentorDbId = (defaultFeatureMentor === null || defaultFeatureMentor === void 0 ? void 0 : defaultFeatureMentor.id) || "";
11404
- const rbacPermissions = await loadMentorsPermissions(defaultFeatureMentorDbId);
11405
- onLoadMentorsPermissions === null || onLoadMentorsPermissions === void 0 ? void 0 : onLoadMentorsPermissions(rbacPermissions);
11406
- redirectToMentor(tenantKey, (defaultFeatureMentor === null || defaultFeatureMentor === void 0 ? void 0 : defaultFeatureMentor.unique_id) || "");
11407
- onAuthSuccess === null || onAuthSuccess === void 0 ? void 0 : onAuthSuccess();
11408
- return;
12050
+ return defaultFeatureMentor;
11409
12051
  }
11410
12052
  }
11411
12053
  // If no default mentor, select the first featured mentor
11412
- const firstFeaturedMentorId = ((_f = featuredMentors[0]) === null || _f === void 0 ? void 0 : _f.unique_id) || "";
11413
- console.log("redirecting to first featured mentor", {
11414
- mentorId: firstFeaturedMentorId,
11415
- mentorName: (_g = featuredMentors[0]) === null || _g === void 0 ? void 0 : _g.name,
12054
+ console.log("found first featured mentor", {
12055
+ mentorId: (_e = featuredMentors[0]) === null || _e === void 0 ? void 0 : _e.unique_id,
12056
+ mentorName: (_f = featuredMentors[0]) === null || _f === void 0 ? void 0 : _f.name,
11416
12057
  });
11417
- const firstFeaturedMentorDbId = ((_h = featuredMentors[0]) === null || _h === void 0 ? void 0 : _h.id) || "";
11418
- const rbacPermissions = await loadMentorsPermissions(firstFeaturedMentorDbId);
11419
- onLoadMentorsPermissions === null || onLoadMentorsPermissions === void 0 ? void 0 : onLoadMentorsPermissions(rbacPermissions);
11420
- redirectToMentor(tenantKey, firstFeaturedMentorId);
11421
- onAuthSuccess === null || onAuthSuccess === void 0 ? void 0 : onAuthSuccess();
11422
- return;
12058
+ return featuredMentors[0];
11423
12059
  }
11424
12060
  // If no featured mentors, get non-featured mentors
11425
12061
  console.log("no featured mentors found, fetching non-featured mentors", {
@@ -11433,24 +12069,18 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
11433
12069
  limit: QUERY_LIMIT,
11434
12070
  orderBy: "recently_accessed_at",
11435
12071
  });
11436
- const nonFeaturedMentors = ((_j = nonFeaturedMentorsResult.data) === null || _j === void 0 ? void 0 : _j.results) || [];
12072
+ const nonFeaturedMentors = ((_g = nonFeaturedMentorsResult.data) === null || _g === void 0 ? void 0 : _g.results) || [];
11437
12073
  console.log("non-featured mentors fetched", {
11438
12074
  count: nonFeaturedMentors.length,
11439
12075
  mentorIds: nonFeaturedMentors.map((m) => m === null || m === void 0 ? void 0 : m.unique_id),
11440
12076
  });
11441
12077
  // Check if we found non-featured mentors
11442
12078
  if (nonFeaturedMentors.length > 0) {
11443
- const firstNonFeaturedMentorId = ((_k = nonFeaturedMentors[0]) === null || _k === void 0 ? void 0 : _k.unique_id) || "";
11444
- console.log("redirecting to first non-featured mentor", {
11445
- mentorId: firstNonFeaturedMentorId,
11446
- mentorName: (_l = nonFeaturedMentors[0]) === null || _l === void 0 ? void 0 : _l.name,
12079
+ console.log("found first non-featured mentor", {
12080
+ mentorId: (_h = nonFeaturedMentors[0]) === null || _h === void 0 ? void 0 : _h.unique_id,
12081
+ mentorName: (_j = nonFeaturedMentors[0]) === null || _j === void 0 ? void 0 : _j.name,
11447
12082
  });
11448
- const firstNonFeaturedMentorDbId = ((_m = nonFeaturedMentors[0]) === null || _m === void 0 ? void 0 : _m.id) || "";
11449
- const rbacPermissions = await loadMentorsPermissions(firstNonFeaturedMentorDbId);
11450
- onLoadMentorsPermissions === null || onLoadMentorsPermissions === void 0 ? void 0 : onLoadMentorsPermissions(rbacPermissions);
11451
- redirectToMentor(tenantKey, firstNonFeaturedMentorId);
11452
- onAuthSuccess === null || onAuthSuccess === void 0 ? void 0 : onAuthSuccess();
11453
- return;
12083
+ return nonFeaturedMentors[0];
11454
12084
  }
11455
12085
  // If no mentors found, check if user is admin
11456
12086
  console.log("no mentors found, checking admin status", {
@@ -11470,7 +12100,7 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
11470
12100
  // @ts-ignore
11471
12101
  userId: username,
11472
12102
  });
11473
- const seededMentorsDetails = (_o = seedMentorsResult.data) === null || _o === void 0 ? void 0 : _o.detail;
12103
+ const seededMentorsDetails = (_k = seedMentorsResult.data) === null || _k === void 0 ? void 0 : _k.detail;
11474
12104
  console.log("mentor seeding completed", {
11475
12105
  success: !!seededMentorsDetails,
11476
12106
  details: seededMentorsDetails,
@@ -11485,29 +12115,23 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
11485
12115
  username,
11486
12116
  limit: QUERY_LIMIT,
11487
12117
  });
11488
- const featuredMentorsAfterSeed = ((_p = featuredMentorsAfterSeedResult.data) === null || _p === void 0 ? void 0 : _p.results) || [];
12118
+ const featuredMentorsAfterSeed = ((_l = featuredMentorsAfterSeedResult.data) === null || _l === void 0 ? void 0 : _l.results) || [];
11489
12119
  console.log("featured mentors after seeding", {
11490
12120
  count: featuredMentorsAfterSeed.length,
11491
12121
  mentorIds: featuredMentorsAfterSeed.map((m) => m === null || m === void 0 ? void 0 : m.unique_id),
11492
12122
  });
11493
12123
  if (featuredMentorsAfterSeed.length > 0) {
11494
- const seededMentorId = ((_q = featuredMentorsAfterSeed[0]) === null || _q === void 0 ? void 0 : _q.unique_id) || "";
11495
- console.log("redirecting to seeded mentor", {
11496
- mentorId: seededMentorId,
11497
- mentorName: (_r = featuredMentorsAfterSeed[0]) === null || _r === void 0 ? void 0 : _r.name,
12124
+ console.log("found seeded mentor", {
12125
+ mentorId: (_m = featuredMentorsAfterSeed[0]) === null || _m === void 0 ? void 0 : _m.unique_id,
12126
+ mentorName: (_o = featuredMentorsAfterSeed[0]) === null || _o === void 0 ? void 0 : _o.name,
11498
12127
  });
11499
- const seededMentorDbId = ((_s = featuredMentorsAfterSeed[0]) === null || _s === void 0 ? void 0 : _s.id) || "";
11500
- const rbacPermissions = await loadMentorsPermissions(seededMentorDbId);
11501
- onLoadMentorsPermissions === null || onLoadMentorsPermissions === void 0 ? void 0 : onLoadMentorsPermissions(rbacPermissions);
11502
- redirectToMentor(tenantKey, seededMentorId);
11503
- onAuthSuccess === null || onAuthSuccess === void 0 ? void 0 : onAuthSuccess();
11504
- return;
12128
+ return featuredMentorsAfterSeed[0];
11505
12129
  }
11506
12130
  else {
11507
12131
  console.log("no seeded mentors found, redirecting to create mentor");
11508
12132
  redirectToCreateMentor();
11509
12133
  onAuthSuccess === null || onAuthSuccess === void 0 ? void 0 : onAuthSuccess();
11510
- return;
12134
+ return undefined;
11511
12135
  }
11512
12136
  }
11513
12137
  else {
@@ -11515,7 +12139,7 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
11515
12139
  // Prompt the user to create a mentor
11516
12140
  redirectToCreateMentor();
11517
12141
  onAuthSuccess === null || onAuthSuccess === void 0 ? void 0 : onAuthSuccess();
11518
- return;
12142
+ return undefined;
11519
12143
  }
11520
12144
  }
11521
12145
  else {
@@ -11526,7 +12150,7 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
11526
12150
  // Redirect to no mentors page for non-admin users
11527
12151
  redirectToNoMentorsPage();
11528
12152
  onAuthSuccess === null || onAuthSuccess === void 0 ? void 0 : onAuthSuccess();
11529
- return;
12153
+ return undefined;
11530
12154
  }
11531
12155
  }
11532
12156
  catch (error) {
@@ -11538,18 +12162,19 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
11538
12162
  isAdmin,
11539
12163
  });
11540
12164
  onAuthFailure === null || onAuthFailure === void 0 ? void 0 : onAuthFailure(`Unexpected error: ${errorMessage}`);
12165
+ console.log("[auth-redirect] Unexpected error in mentor provider", {
12166
+ error: errorMessage,
12167
+ });
11541
12168
  redirectToAuthSpa();
12169
+ return undefined;
11542
12170
  }
11543
12171
  finally {
11544
12172
  setIsLoading(false);
12173
+ onComplete === null || onComplete === void 0 ? void 0 : onComplete();
11545
12174
  }
11546
12175
  }
11547
12176
  async function mentorExistsInTenant(tenantKey, requestedMentorId) {
11548
- console.log("checking if mentor exists in tenant", {
11549
- tenantKey,
11550
- requestedMentorId,
11551
- username,
11552
- });
12177
+ console.log("checking if mentor exists in tenant", tenantKey, requestedMentorId, username);
11553
12178
  try {
11554
12179
  const response = await getMentorPublicSettings({
11555
12180
  // @ts-ignore
@@ -11578,13 +12203,10 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
11578
12203
  // Effect to handle mentor determination when tenant path is determined
11579
12204
  React.useEffect(() => {
11580
12205
  async function checkMentor() {
11581
- console.log("starting mentor check process", {
11582
- determineUserPath,
11583
- requestedMentorId,
11584
- tenantKey,
11585
- });
12206
+ console.log("starting mentor check process", determineUserPath, requestedMentorId, tenantKey);
11586
12207
  if (userIsAccessingPublicRoute && !requestedMentorId) {
11587
12208
  setIsLoading(false);
12209
+ onComplete === null || onComplete === void 0 ? void 0 : onComplete();
11588
12210
  return;
11589
12211
  }
11590
12212
  setIsLoading(true);
@@ -11592,50 +12214,83 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
11592
12214
  // then this mentor provider will redirect the user to the correct mentor.
11593
12215
  if (determineUserPath || forceDetermineMentor) {
11594
12216
  console.log("determine user path is true, starting mentor determination");
11595
- await determineMentorToRedirectTo();
12217
+ const mentor = await determineMentorToRedirectTo();
12218
+ if (mentor === null || mentor === void 0 ? void 0 : mentor.unique_id) {
12219
+ // Get mentor DB ID - use existing ID or fetch from public settings
12220
+ let mentorDbId = mentor === null || mentor === void 0 ? void 0 : mentor.id;
12221
+ if (!mentorDbId) {
12222
+ mentorDbId = await getMentorDbId(mentor);
12223
+ }
12224
+ // Load permissions if we have a mentor DB ID
12225
+ if (mentorDbId) {
12226
+ const rbacPermissions = await loadMentorsPermissions(mentorDbId);
12227
+ onLoadMentorsPermissions === null || onLoadMentorsPermissions === void 0 ? void 0 : onLoadMentorsPermissions(rbacPermissions);
12228
+ }
12229
+ // Redirect to the mentor
12230
+ redirectToMentor(tenantKey, mentor.unique_id);
12231
+ onAuthSuccess === null || onAuthSuccess === void 0 ? void 0 : onAuthSuccess();
12232
+ }
11596
12233
  return;
11597
12234
  }
11598
12235
  else if (requestedMentorId) {
11599
- console.log(" ", {
11600
- requestedMentorId,
11601
- });
11602
12236
  const [mentorExists, requestedMentorDbId] = await mentorExistsInTenant(tenantKey, requestedMentorId);
11603
12237
  // If the mentor does not exist in the tenant, redirect the user to the correct mentor
11604
12238
  if (!mentorExists) {
11605
- console.log("requested mentor not found in tenant", {
12239
+ console.log("requested mentor not found in tenant", JSON.stringify({
11606
12240
  requestedMentorId,
11607
12241
  tenantKey,
11608
12242
  hasCustomHandler: !!handleMentorNotFound,
11609
- });
12243
+ }));
11610
12244
  if (handleMentorNotFound) {
11611
12245
  console.log("calling custom mentor not found handler");
11612
12246
  await handleMentorNotFound();
11613
12247
  }
11614
12248
  else {
11615
12249
  console.log("using default mentor determination fallback");
11616
- await determineMentorToRedirectTo();
12250
+ const mentor = await determineMentorToRedirectTo();
12251
+ if (mentor === null || mentor === void 0 ? void 0 : mentor.unique_id) {
12252
+ // Get mentor DB ID - use existing ID or fetch from public settings
12253
+ let mentorDbId = mentor === null || mentor === void 0 ? void 0 : mentor.id;
12254
+ if (!mentorDbId) {
12255
+ mentorDbId = await getMentorDbId(mentor);
12256
+ }
12257
+ // Load permissions if we have a mentor DB ID
12258
+ if (mentorDbId) {
12259
+ const rbacPermissions = await loadMentorsPermissions(mentorDbId);
12260
+ onLoadMentorsPermissions === null || onLoadMentorsPermissions === void 0 ? void 0 : onLoadMentorsPermissions(rbacPermissions);
12261
+ }
12262
+ // Redirect to the mentor
12263
+ redirectToMentor(tenantKey, mentor.unique_id);
12264
+ onAuthSuccess === null || onAuthSuccess === void 0 ? void 0 : onAuthSuccess();
12265
+ }
11617
12266
  }
11618
12267
  return;
11619
12268
  }
11620
12269
  else {
11621
- console.log("requested mentor exists in tenant, proceeding", {
11622
- requestedMentorId,
11623
- });
12270
+ console.log("requested mentor exists in tenant, proceeding", requestedMentorId);
11624
12271
  if (requestedMentorDbId) {
11625
12272
  const rbacPermissions = await loadMentorsPermissions(requestedMentorDbId);
11626
12273
  onLoadMentorsPermissions === null || onLoadMentorsPermissions === void 0 ? void 0 : onLoadMentorsPermissions(rbacPermissions);
11627
12274
  }
11628
12275
  setIsLoading(false);
12276
+ onComplete === null || onComplete === void 0 ? void 0 : onComplete();
11629
12277
  }
11630
12278
  // If the user is navigating to a specific mentor, check if it exists in the tenant
11631
12279
  }
11632
12280
  else {
11633
12281
  console.log("no specific mentor requested, loading complete");
11634
12282
  setIsLoading(false);
12283
+ onComplete === null || onComplete === void 0 ? void 0 : onComplete();
11635
12284
  }
11636
12285
  }
11637
12286
  checkMentor();
11638
- }, []);
12287
+ }, [
12288
+ requestedMentorId,
12289
+ determineUserPath,
12290
+ forceDetermineMentor,
12291
+ userIsAccessingPublicRoute,
12292
+ tenantKey,
12293
+ ]);
11639
12294
  // Show fallback component during mentor determination
11640
12295
  if (isLoading) {
11641
12296
  console.log("mentor provider showing fallback component");
@@ -12092,7 +12747,7 @@ function formatProdErrorMessage(code) {
12092
12747
 
12093
12748
  const defaultSessionIds = Object.fromEntries(Object.keys(advancedTabsProperties).map((key) => [key, ""]));
12094
12749
  const defaultChatState = Object.fromEntries(Object.keys(advancedTabsProperties).map((key) => [key, []]));
12095
- const initialState = {
12750
+ const initialState$1 = {
12096
12751
  chats: defaultChatState,
12097
12752
  isTyping: false,
12098
12753
  streaming: false,
@@ -12120,7 +12775,7 @@ const initialState = {
12120
12775
  };
12121
12776
  const chatSlice = createSlice({
12122
12777
  name: "chatSliceShared",
12123
- initialState,
12778
+ initialState: initialState$1,
12124
12779
  reducers: {
12125
12780
  setChats: (state, action) => {
12126
12781
  state.chats = action.payload;
@@ -12224,6 +12879,25 @@ const chatSlice = createSlice({
12224
12879
  setShowingSharedChat: (state, action) => {
12225
12880
  state.showingSharedChat = action.payload;
12226
12881
  },
12882
+ updateFileUrlInMessage: (state, action) => {
12883
+ const { fileId, fileUrl } = action.payload;
12884
+ // Update all tabs' messages that have this file
12885
+ Object.keys(state.chats).forEach((tab) => {
12886
+ state.chats[tab] = state.chats[tab].map((message) => {
12887
+ if (message.fileAttachments && message.fileAttachments.length > 0) {
12888
+ const updatedAttachments = message.fileAttachments.map((attachment) => {
12889
+ // Match by fileId
12890
+ if (attachment.fileId === fileId) {
12891
+ return { ...attachment, uploadUrl: fileUrl };
12892
+ }
12893
+ return attachment;
12894
+ });
12895
+ return { ...message, fileAttachments: updatedAttachments };
12896
+ }
12897
+ return message;
12898
+ });
12899
+ });
12900
+ },
12227
12901
  },
12228
12902
  });
12229
12903
  const chatActions = chatSlice.actions;
@@ -12507,6 +13181,61 @@ function useTimeTrackerNative(config) {
12507
13181
  };
12508
13182
  }
12509
13183
 
13184
+ const initialState = {
13185
+ attachedFiles: [],
13186
+ };
13187
+ const filesSlice = createSlice({
13188
+ name: "files",
13189
+ initialState,
13190
+ reducers: {
13191
+ addFiles: (state, action) => {
13192
+ state.attachedFiles = [...state.attachedFiles, ...action.payload];
13193
+ },
13194
+ updateFileProgress: (state, action) => {
13195
+ state.attachedFiles = state.attachedFiles.map((file) => file.id === action.payload.id
13196
+ ? { ...file, uploadProgress: action.payload.progress }
13197
+ : file);
13198
+ },
13199
+ updateFileStatus: (state, action) => {
13200
+ state.attachedFiles = state.attachedFiles.map((file) => file.id === action.payload.id
13201
+ ? { ...file, uploadStatus: action.payload.status }
13202
+ : file);
13203
+ },
13204
+ updateFileUrl: (state, action) => {
13205
+ state.attachedFiles = state.attachedFiles.map((file) => file.id === action.payload.id
13206
+ ? { ...file, uploadUrl: action.payload.uploadUrl }
13207
+ : file);
13208
+ },
13209
+ updateFileMetadata: (state, action) => {
13210
+ state.attachedFiles = state.attachedFiles.map((file) => file.id === action.payload.id
13211
+ ? {
13212
+ ...file,
13213
+ fileKey: action.payload.fileKey,
13214
+ fileId: action.payload.fileId,
13215
+ }
13216
+ : file);
13217
+ },
13218
+ updateFileRetryCount: (state, action) => {
13219
+ state.attachedFiles = state.attachedFiles.map((file) => file.id === action.payload.id
13220
+ ? { ...file, retryCount: action.payload.retryCount }
13221
+ : file);
13222
+ },
13223
+ updateFileUrlFromWebSocket: (state, action) => {
13224
+ state.attachedFiles = state.attachedFiles.map((file) => file.fileId === action.payload.fileId
13225
+ ? { ...file, fileUrl: action.payload.fileUrl }
13226
+ : file);
13227
+ },
13228
+ removeFile: (state, action) => {
13229
+ state.attachedFiles = state.attachedFiles.filter((file) => file.id !== action.payload);
13230
+ },
13231
+ clearFiles: (state) => {
13232
+ state.attachedFiles = [];
13233
+ },
13234
+ },
13235
+ });
13236
+ const { addFiles, removeFile, clearFiles, updateFileProgress, updateFileStatus, updateFileUrl, updateFileMetadata, updateFileRetryCount, updateFileUrlFromWebSocket, } = filesSlice.actions;
13237
+ const filesReducer = filesSlice.reducer;
13238
+
12510
13239
  const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, enableHaptics = false, hapticFeedback, store, errorHandler, onStatusChange, onStreamingChange, onStreamingMessageUpdate, WebSocketImpl = WebSocket, redirectToAuthSpa, sendMessageToParentWebsite, on402Error, }) => {
12511
13240
  const dispatch = useDispatch();
12512
13241
  const isWebSocketPaused = React.useRef(false);
@@ -12530,7 +13259,7 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
12530
13259
  await hapticFeedback.impactAsync("medium");
12531
13260
  }
12532
13261
  catch (error) {
12533
- console.warn("Haptic feedback failed:", error);
13262
+ errorHandler === null || errorHandler === void 0 ? void 0 : errorHandler("Haptic feedback failed", error);
12534
13263
  }
12535
13264
  }
12536
13265
  }, [enableHaptics, hapticFeedback]);
@@ -12542,8 +13271,8 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
12542
13271
  }
12543
13272
  if (!wsToken) {
12544
13273
  if (!userIsAccessingPublicRoute) {
12545
- console.error("Token is missing for non-anonymous user");
12546
- redirectToAuthSpa();
13274
+ console.log("[auth-redirect] WebSocket token is missing for non-anonymous user");
13275
+ redirectToAuthSpa(undefined, undefined, true);
12547
13276
  return;
12548
13277
  }
12549
13278
  }
@@ -12577,6 +13306,7 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
12577
13306
  onStreamingChange === null || onStreamingChange === void 0 ? void 0 : onStreamingChange(false);
12578
13307
  });
12579
13308
  socket.addEventListener("message", (event) => {
13309
+ var _a, _b, _c;
12580
13310
  if (isWebSocketPaused.current)
12581
13311
  return;
12582
13312
  try {
@@ -12598,6 +13328,16 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
12598
13328
  onStreamingChange(!!messageData.isTyping);
12599
13329
  return;
12600
13330
  }
13331
+ // Handle file processing success
13332
+ if (messageData.type === "file_processing_success") {
13333
+ console.log("🟣 File processing success:", messageData);
13334
+ dispatch(chatActions.updateFileUrlInMessage({
13335
+ fileId: messageData.file_id,
13336
+ fileName: messageData.file_name,
13337
+ fileUrl: messageData.file_url,
13338
+ }));
13339
+ return;
13340
+ }
12601
13341
  // Handle start of new streaming session
12602
13342
  if (messageData.generation_id &&
12603
13343
  !messageData.data &&
@@ -12616,14 +13356,14 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
12616
13356
  if (messageData.data !== undefined || messageData.eos !== undefined) {
12617
13357
  const messageText = messageData.data || "";
12618
13358
  // If we have content to add
12619
- if (messageText) {
13359
+ if (messageText && currentStreamingMessage.current) {
12620
13360
  currentStreamingMessage.current = {
12621
13361
  ...currentStreamingMessage.current,
12622
13362
  content: currentStreamingMessage.current.content + messageText,
12623
13363
  };
12624
13364
  onStreamingMessageUpdate === null || onStreamingMessageUpdate === void 0 ? void 0 : onStreamingMessageUpdate(currentStreamingMessage.current);
12625
13365
  // Update or add message in Redux store
12626
- if (currentStreamingMessage.current.id) {
13366
+ if ((_a = currentStreamingMessage.current) === null || _a === void 0 ? void 0 : _a.id) {
12627
13367
  dispatch(chatActions.appendMessageToActiveTab({
12628
13368
  id: currentStreamingMessage.current.id,
12629
13369
  content: currentStreamingMessage.current.content,
@@ -12633,8 +13373,8 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
12633
13373
  // Handle end of stream
12634
13374
  if (messageData.eos) {
12635
13375
  // Final update to Redux store with complete message
12636
- if (currentStreamingMessage.current.id &&
12637
- currentStreamingMessage.current.content) {
13376
+ if (((_b = currentStreamingMessage.current) === null || _b === void 0 ? void 0 : _b.id) &&
13377
+ ((_c = currentStreamingMessage.current) === null || _c === void 0 ? void 0 : _c.content)) {
12638
13378
  dispatch(chatActions.appendMessageToActiveTab({
12639
13379
  id: currentStreamingMessage.current.id,
12640
13380
  content: currentStreamingMessage.current.content,
@@ -12649,13 +13389,13 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
12649
13389
  }
12650
13390
  }
12651
13391
  catch (error) {
12652
- console.error("Error processing message:", error);
13392
+ errorHandler === null || errorHandler === void 0 ? void 0 : errorHandler("Error processing message", error);
12653
13393
  onStreamingChange === null || onStreamingChange === void 0 ? void 0 : onStreamingChange(false);
12654
13394
  onStatusChange("error");
12655
13395
  }
12656
13396
  });
12657
13397
  socket.addEventListener("error", (error) => {
12658
- console.error("WebSocket error:", error);
13398
+ errorHandler === null || errorHandler === void 0 ? void 0 : errorHandler("WebSocket error", error);
12659
13399
  onStreamingChange === null || onStreamingChange === void 0 ? void 0 : onStreamingChange(false);
12660
13400
  onStatusChange("error");
12661
13401
  });
@@ -12693,19 +13433,31 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
12693
13433
  };
12694
13434
  };
12695
13435
  const sendMessage = React.useCallback(async (tab, text, options) => {
12696
- var _a;
13436
+ var _a, _b;
12697
13437
  dispatch(chatActions.setShowingSharedChat(false));
12698
- if (!text.trim())
13438
+ // Allow sending if there's text OR file references
13439
+ if (!text.trim() &&
13440
+ (!(options === null || options === void 0 ? void 0 : options.fileReferences) || options.fileReferences.length === 0)) {
12699
13441
  return;
13442
+ }
12700
13443
  onStatusChange("pending");
12701
13444
  isWebSocketPaused.current = false;
12702
13445
  await triggerHapticFeedback();
13446
+ // Create file attachments array from file references if present
13447
+ const fileAttachments = (_a = options === null || options === void 0 ? void 0 : options.fileReferences) === null || _a === void 0 ? void 0 : _a.map((ref) => ({
13448
+ fileName: ref.file_name,
13449
+ fileType: ref.content_type,
13450
+ fileSize: ref.file_size,
13451
+ uploadUrl: ref.upload_url, // Include URL for display
13452
+ fileId: ref.file_id, // Include fileId for matching WebSocket updates
13453
+ }));
12703
13454
  const userMessage = {
12704
13455
  id: `user-${Date.now()}`,
12705
13456
  role: "user",
12706
13457
  content: text,
12707
13458
  timestamp: new Date().toISOString(),
12708
- visible: (_a = options === null || options === void 0 ? void 0 : options.visible) !== null && _a !== void 0 ? _a : true,
13459
+ visible: (_b = options === null || options === void 0 ? void 0 : options.visible) !== null && _b !== void 0 ? _b : true,
13460
+ fileAttachments,
12709
13461
  };
12710
13462
  // Notify parent to add user message
12711
13463
  // onAddUserMessage?.(tab, userMessage);
@@ -12717,8 +13469,14 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
12717
13469
  flow: flowConfig,
12718
13470
  session_id: sessionId,
12719
13471
  token: wsToken,
12720
- prompt: text,
13472
+ prompt: text || "", // Allow empty prompt when sending files
12721
13473
  };
13474
+ if ((options === null || options === void 0 ? void 0 : options.fileReferences) && options.fileReferences.length > 0) {
13475
+ messageData = {
13476
+ ...messageData,
13477
+ file_references: options.fileReferences,
13478
+ };
13479
+ }
12722
13480
  if (iframeContext.pageContent) {
12723
13481
  messageData = {
12724
13482
  ...messageData,
@@ -12788,8 +13546,12 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
12788
13546
  }
12789
13547
  };
12790
13548
  const _initiateServerStopGeneration = () => {
12791
- var _a;
12792
- (_a = stopGenerationSocket === null || stopGenerationSocket === void 0 ? void 0 : stopGenerationSocket.current) === null || _a === void 0 ? void 0 : _a.send(JSON.stringify({
13549
+ var _a, _b;
13550
+ if (!((_a = currentStreamingMessage.current) === null || _a === void 0 ? void 0 : _a.id)) {
13551
+ console.warn("Cannot stop generation: no active generation ID");
13552
+ return;
13553
+ }
13554
+ (_b = stopGenerationSocket === null || stopGenerationSocket === void 0 ? void 0 : stopGenerationSocket.current) === null || _b === void 0 ? void 0 : _b.send(JSON.stringify({
12793
13555
  generation_id: currentStreamingMessage.current.id,
12794
13556
  name: flowConfig.name,
12795
13557
  tenant: flowConfig.tenant,
@@ -12849,7 +13611,7 @@ const useChat = ({ wsUrl, wsToken, flowConfig, sessionId, stopGenerationWsUrl, e
12849
13611
  };
12850
13612
  };
12851
13613
 
12852
- function useMentorSettings({ mentorId, tenantKey, username }) {
13614
+ function useMentorSettings({ mentorId, tenantKey, username, }) {
12853
13615
  var _a, _b, _c, _d;
12854
13616
  const isLoggedIn = username !== ANONYMOUS_USERNAME;
12855
13617
  const { data: mentorSettings } = useGetMentorSettingsQuery({
@@ -12885,6 +13647,9 @@ function useMentorSettings({ mentorId, tenantKey, username }) {
12885
13647
  mentorUniqueId: isLoggedIn
12886
13648
  ? mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.mentor_unique_id
12887
13649
  : mentorPublicSettings === null || mentorPublicSettings === void 0 ? void 0 : mentorPublicSettings.mentor_unique_id,
13650
+ mentorVisibility: isLoggedIn
13651
+ ? mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.mentor_visibility
13652
+ : mentorPublicSettings === null || mentorPublicSettings === void 0 ? void 0 : mentorPublicSettings.mentor_visibility,
12888
13653
  mentorName: (_a = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.mentor) !== null && _a !== void 0 ? _a : mentorPublicSettings === null || mentorPublicSettings === void 0 ? void 0 : mentorPublicSettings.mentor,
12889
13654
  enableGuidedPrompts: isLoggedIn
12890
13655
  ? mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.enable_guided_prompts
@@ -12903,8 +13668,8 @@ function useMentorSettings({ mentorId, tenantKey, username }) {
12903
13668
  };
12904
13669
  }
12905
13670
 
12906
- function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, token, wsUrl, stopGenerationWsUrl, redirectToAuthSpa, errorHandler, sendMessageToParentWebsite, isPreviewMode, mentorShareableToken, on402Error, }) {
12907
- var _a, _b, _c, _d;
13671
+ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, token, wsUrl, stopGenerationWsUrl, redirectToAuthSpa, errorHandler, sendMessageToParentWebsite, isPreviewMode, mentorShareableToken, on402Error, cachedSessionId, onStartNewChat, }) {
13672
+ var _a, _b, _c, _d, _e;
12908
13673
  const dispatch = useDispatch();
12909
13674
  const [createSessionId, { isLoading: isLoadingSessionIds }] = useCreateSessionIdMutation();
12910
13675
  const chats = useSelector(selectChats);
@@ -12942,7 +13707,7 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
12942
13707
  username,
12943
13708
  pathway: mentorId,
12944
13709
  },
12945
- sessionId: sessionIds[activeTab],
13710
+ sessionId: (_a = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[mentorId]) !== null && _a !== void 0 ? _a : sessionIds[activeTab],
12946
13711
  activeTab,
12947
13712
  wsToken: token,
12948
13713
  errorHandler,
@@ -12953,6 +13718,56 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
12953
13718
  onStatusChange,
12954
13719
  on402Error,
12955
13720
  });
13721
+ const [getSessionChats, { isError: isErrorGettingSessionChats }] = useLazyGetSessionIdQuery();
13722
+ React.useEffect(() => {
13723
+ const getChats = async () => {
13724
+ var _a, _b;
13725
+ try {
13726
+ const { data } = await getSessionChats({
13727
+ sessionId: (_a = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[mentorId]) !== null && _a !== void 0 ? _a : "",
13728
+ org: tenantKey,
13729
+ share: true,
13730
+ });
13731
+ let previousChats = [];
13732
+ try {
13733
+ previousChats =
13734
+ ((_b = data === null || data === void 0 ? void 0 : data.results) === null || _b === void 0 ? void 0 : _b.map((result) => {
13735
+ return {
13736
+ ...result,
13737
+ role: result.type === "human" ? "user" : "assistant",
13738
+ visible: true,
13739
+ id: new Date().getTime(),
13740
+ content: typeof result.content === "object" &&
13741
+ result.content.length > 0
13742
+ ? result.content[0].text
13743
+ : result.content,
13744
+ };
13745
+ }).reverse()) || [];
13746
+ }
13747
+ catch (error) {
13748
+ console.error(JSON.stringify(error));
13749
+ }
13750
+ // Ensures that the first AI response due to a Proactive prompt
13751
+ // doesn't show up as part of the chats
13752
+ if ((data === null || data === void 0 ? void 0 : data.proactive_prompt) &&
13753
+ previousChats.length > 0 &&
13754
+ previousChats[0].type === "ai") {
13755
+ previousChats.splice(0, 1);
13756
+ }
13757
+ dispatch(chatActions.setNewMessages(previousChats));
13758
+ }
13759
+ catch (error) {
13760
+ console.error(JSON.stringify(error));
13761
+ }
13762
+ };
13763
+ if (cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[mentorId]) {
13764
+ dispatch(chatActions.updateSessionIds(cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[mentorId]));
13765
+ getChats();
13766
+ }
13767
+ }, [cachedSessionId]);
13768
+ React.useEffect(() => {
13769
+ }, [isErrorGettingSessionChats]);
13770
+ React.useEffect(() => { }, []);
12956
13771
  const startNewChat = React.useCallback(async () => {
12957
13772
  // Reset all chat state
12958
13773
  if (!showingSharedChat) {
@@ -12962,6 +13777,7 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
12962
13777
  dispatch(chatActions.setStreaming(false));
12963
13778
  dispatch(chatActions.resetCurrentStreamingMessage(undefined));
12964
13779
  dispatch(chatActions.setTools([]));
13780
+ dispatch(clearFiles(undefined));
12965
13781
  if (isPreviewMode) {
12966
13782
  return;
12967
13783
  }
@@ -12972,6 +13788,7 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
12972
13788
  // @ts-ignore
12973
13789
  requestBody["shareable_link_token"] = mentorShareableToken;
12974
13790
  }
13791
+ console.log("[startNewChat] requestBody", tenantKey, username, JSON.stringify(requestBody));
12975
13792
  const response = await createSessionId({
12976
13793
  org: tenantKey,
12977
13794
  // @ts-ignore
@@ -12979,10 +13796,15 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
12979
13796
  requestBody,
12980
13797
  }).unwrap();
12981
13798
  dispatch(chatActions.updateSessionIds(response.session_id));
12982
- // dispatch(chatActions.setShouldStartNewChat(false));
13799
+ onStartNewChat === null || onStartNewChat === void 0 ? void 0 : onStartNewChat(response.session_id);
12983
13800
  }
12984
13801
  catch (error) {
12985
- errorHandler === null || errorHandler === void 0 ? void 0 : errorHandler("Failed to start new chat");
13802
+ if (mentorSettings.mentorVisibility !==
13803
+ iblaiApi.MentorVisibilityEnum.VIEWABLE_BY_ANYONE) {
13804
+ errorHandler === null || errorHandler === void 0 ? void 0 : errorHandler(`Failed to start new chat: ${JSON.stringify(error)}`);
13805
+ console.log("[auth-redirect] Failed to start new chat", JSON.stringify({ error }));
13806
+ redirectToAuthSpa(undefined, undefined, true);
13807
+ }
12986
13808
  }
12987
13809
  }, [
12988
13810
  isPreviewMode,
@@ -12996,7 +13818,8 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
12996
13818
  ]);
12997
13819
  React.useEffect(() => {
12998
13820
  if (!showingSharedChat || mentorSettings.allowAnonymous) {
12999
- if (mentorSettings.allowAnonymous !== undefined) {
13821
+ if (mentorSettings.allowAnonymous !== undefined &&
13822
+ !(cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[mentorId])) {
13000
13823
  startNewChat();
13001
13824
  }
13002
13825
  }
@@ -13048,7 +13871,7 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
13048
13871
  }
13049
13872
  }
13050
13873
  catch (error) {
13051
- errorHandler === null || errorHandler === void 0 ? void 0 : errorHandler("Failed to start new chat");
13874
+ errorHandler === null || errorHandler === void 0 ? void 0 : errorHandler(`Failed to start new chat: ${error}`);
13052
13875
  return;
13053
13876
  }
13054
13877
  }
@@ -13068,9 +13891,9 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
13068
13891
  currentStreamingMessage,
13069
13892
  activeTab,
13070
13893
  uniqueMentorId: mentorId,
13071
- mentorName: (_a = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.mentorName) !== null && _a !== void 0 ? _a : "",
13072
- profileImage: (_b = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.profileImage) !== null && _b !== void 0 ? _b : "",
13073
- enabledGuidedPrompts: (_c = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.enableGuidedPrompts) !== null && _c !== void 0 ? _c : true,
13894
+ mentorName: (_b = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.mentorName) !== null && _b !== void 0 ? _b : "",
13895
+ profileImage: (_c = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.profileImage) !== null && _c !== void 0 ? _c : "",
13896
+ enabledGuidedPrompts: (_d = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.enableGuidedPrompts) !== null && _d !== void 0 ? _d : true,
13074
13897
  sendMessage,
13075
13898
  stopGenerating,
13076
13899
  setMessage,
@@ -13082,7 +13905,7 @@ function useAdvancedChat({ tenantKey, mentorId, username = ANONYMOUS_USERNAME, t
13082
13905
  isConnected,
13083
13906
  messageQueue,
13084
13907
  sessionIds,
13085
- enableSafetyDisclaimer: (_d = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.safetyDisclaimer) !== null && _d !== void 0 ? _d : false,
13908
+ enableSafetyDisclaimer: (_e = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.safetyDisclaimer) !== null && _e !== void 0 ? _e : false,
13086
13909
  resetConnection,
13087
13910
  };
13088
13911
  }
@@ -17938,11 +18761,130 @@ const tenantSchema = z.object({
17938
18761
  });
17939
18762
  const tenantKeySchema = z.string().min(1);
17940
18763
 
18764
+ /**
18765
+ * Chat area size constants
18766
+ */
18767
+ const CHAT_AREA_SIZE = {
18768
+ DEFAULT: 672,
18769
+ MIN: 672,
18770
+ MAX: 1024,
18771
+ };
18772
+
18773
+ /**
18774
+ * Extract file information from File object
18775
+ */
18776
+ function getFileInfo(file) {
18777
+ const fileName = file.name;
18778
+ const contentType = file.type || "application/octet-stream";
18779
+ const fileSize = file.size;
18780
+ return {
18781
+ fileName,
18782
+ contentType,
18783
+ fileSize,
18784
+ };
18785
+ }
18786
+ /**
18787
+ * Request presigned S3 URL from backend
18788
+ * Note: This function should be called via the RTK Query mutation hook
18789
+ * This is a helper to show the data flow
18790
+ */
18791
+ async function requestPresignedUrl(sessionId, file, getUploadUrlFn, org, userId) {
18792
+ const { fileName, contentType, fileSize } = getFileInfo(file);
18793
+ return await getUploadUrlFn({
18794
+ org,
18795
+ userId,
18796
+ requestBody: {
18797
+ session_id: sessionId,
18798
+ file_name: fileName,
18799
+ content_type: contentType,
18800
+ file_size: fileSize,
18801
+ },
18802
+ });
18803
+ }
18804
+ /**
18805
+ * Upload file directly to S3 using presigned URL
18806
+ * Uses axios for cross-platform support (web + React Native)
18807
+ */
18808
+ async function uploadToS3(presignedUrl, file, contentType, onProgress) {
18809
+ await axios.put(presignedUrl, file, {
18810
+ headers: {
18811
+ "Content-Type": contentType,
18812
+ },
18813
+ onUploadProgress: (progressEvent) => {
18814
+ if (onProgress && progressEvent.total) {
18815
+ const progress = Math.round((progressEvent.loaded / progressEvent.total) * 100);
18816
+ onProgress(progress);
18817
+ }
18818
+ },
18819
+ });
18820
+ }
18821
+ /**
18822
+ * Complete file upload flow:
18823
+ * 1. Request presigned URL
18824
+ * 2. Upload to S3
18825
+ * 3. Return file reference
18826
+ */
18827
+ async function createFileReference(file, sessionId, getUploadUrlFn, org, userId, onProgress) {
18828
+ // Step 1: Get presigned URL
18829
+ const presignedResponse = await requestPresignedUrl(sessionId, file, getUploadUrlFn, org, userId);
18830
+ // Step 2: Upload to S3
18831
+ const { fileName, contentType, fileSize } = getFileInfo(file);
18832
+ await uploadToS3(presignedResponse.upload_url, file, contentType, onProgress);
18833
+ // Step 3: Return file reference
18834
+ return {
18835
+ file_id: presignedResponse.file_id,
18836
+ file_key: presignedResponse.file_key,
18837
+ file_name: fileName,
18838
+ content_type: contentType,
18839
+ file_size: fileSize,
18840
+ };
18841
+ }
18842
+ /**
18843
+ * Upload multiple files and return their references
18844
+ */
18845
+ async function createMultipleFileReferences(files, sessionId, getUploadUrlFn, org, userId, onFileProgress) {
18846
+ const fileReferences = [];
18847
+ for (let i = 0; i < files.length; i++) {
18848
+ const file = files[i];
18849
+ const onProgress = onFileProgress
18850
+ ? (progress) => onFileProgress(i, progress)
18851
+ : undefined;
18852
+ const fileReference = await createFileReference(file, sessionId, getUploadUrlFn, org, userId, onProgress);
18853
+ fileReferences.push(fileReference);
18854
+ }
18855
+ return fileReferences;
18856
+ }
18857
+ /**
18858
+ * Validate file before upload
18859
+ * Returns error message if invalid, null if valid
18860
+ */
18861
+ function validateFile(file, maxSizeBytes, allowedTypes) {
18862
+ var _a;
18863
+ // Check file size
18864
+ if (maxSizeBytes && file.size > maxSizeBytes) {
18865
+ const maxSizeMB = (maxSizeBytes / (1024 * 1024)).toFixed(2);
18866
+ const fileSizeMB = (file.size / (1024 * 1024)).toFixed(2);
18867
+ return `File size (${fileSizeMB}MB) exceeds maximum allowed size (${maxSizeMB}MB)`;
18868
+ }
18869
+ // Check file type
18870
+ if (allowedTypes && allowedTypes.length > 0) {
18871
+ const fileExtension = (_a = file.name.split(".").pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase();
18872
+ const fileType = file.type.toLowerCase();
18873
+ const isTypeAllowed = allowedTypes.some((allowed) => fileType.includes(allowed.toLowerCase()) ||
18874
+ fileExtension === allowed.toLowerCase().replace(".", ""));
18875
+ if (!isTypeAllowed) {
18876
+ return `File type not allowed. Allowed types: ${allowedTypes.join(", ")}`;
18877
+ }
18878
+ }
18879
+ return null;
18880
+ }
18881
+
17941
18882
  exports.ALPHANUMERIC_32_REGEX = ALPHANUMERIC_32_REGEX;
17942
18883
  exports.ANONYMOUS_USERNAME = ANONYMOUS_USERNAME;
17943
18884
  exports.AuthContext = AuthContext;
17944
18885
  exports.AuthContextProvider = AuthContextProvider;
17945
18886
  exports.AuthProvider = AuthProvider;
18887
+ exports.CHAT_AREA_SIZE = CHAT_AREA_SIZE;
17946
18888
  exports.LOCAL_STORAGE_KEYS = LOCAL_STORAGE_KEYS;
17947
18889
  exports.MAX_INITIAL_WEBSOCKET_CONNECTION_ATTEMPTS = MAX_INITIAL_WEBSOCKET_CONNECTION_ATTEMPTS;
17948
18890
  exports.MENTOR_CHAT_DOCUMENTS_EXTENSIONS = MENTOR_CHAT_DOCUMENTS_EXTENSIONS;
@@ -17959,20 +18901,42 @@ exports.TenantContext = TenantContext;
17959
18901
  exports.TenantContextProvider = TenantContextProvider;
17960
18902
  exports.TenantProvider = TenantProvider;
17961
18903
  exports.TimeTracker = TimeTracker;
18904
+ exports.addFiles = addFiles;
17962
18905
  exports.addProtocolToUrl = addProtocolToUrl;
17963
18906
  exports.advancedTabs = advancedTabs;
17964
18907
  exports.advancedTabsProperties = advancedTabsProperties;
17965
18908
  exports.chatActions = chatActions;
17966
18909
  exports.chatSliceReducerShared = chatSliceReducerShared;
17967
18910
  exports.clearAuthCookies = clearAuthCookies;
18911
+ exports.clearCookies = clearCookies;
18912
+ exports.clearCurrentTenantCookie = clearCurrentTenantCookie;
18913
+ exports.clearFiles = clearFiles;
18914
+ exports.createFileReference = createFileReference;
18915
+ exports.createMultipleFileReferences = createMultipleFileReferences;
17968
18916
  exports.defaultSessionIds = defaultSessionIds;
18917
+ exports.deleteCookie = deleteCookie;
18918
+ exports.deleteCookieOnAllDomains = deleteCookieOnAllDomains;
18919
+ exports.filesReducer = filesReducer;
18920
+ exports.filesSlice = filesSlice;
17969
18921
  exports.formatRelativeTime = formatRelativeTime;
18922
+ exports.getAuthSpaJoinUrl = getAuthSpaJoinUrl;
18923
+ exports.getDomainParts = getDomainParts;
18924
+ exports.getFileInfo = getFileInfo;
17970
18925
  exports.getInitials = getInitials;
18926
+ exports.getParentDomain = getParentDomain;
18927
+ exports.getPlatformKey = getPlatformKey;
17971
18928
  exports.getTimeAgo = getTimeAgo;
17972
18929
  exports.getUserName = getUserName;
18930
+ exports.handleLogout = handleLogout;
17973
18931
  exports.isAlphaNumeric32 = isAlphaNumeric32;
18932
+ exports.isInIframe = isInIframe;
17974
18933
  exports.isJSON = isJSON;
18934
+ exports.isLoggedIn = isLoggedIn;
17975
18935
  exports.loadMetadataConfig = loadMetadataConfig;
18936
+ exports.redirectToAuthSpa = redirectToAuthSpa;
18937
+ exports.redirectToAuthSpaJoinTenant = redirectToAuthSpaJoinTenant;
18938
+ exports.removeFile = removeFile;
18939
+ exports.requestPresignedUrl = requestPresignedUrl;
17976
18940
  exports.selectActiveChatMessages = selectActiveChatMessages;
17977
18941
  exports.selectActiveTab = selectActiveTab;
17978
18942
  exports.selectChats = selectChats;
@@ -17993,10 +18957,19 @@ exports.selectStreaming = selectStreaming;
17993
18957
  exports.selectToken = selectToken;
17994
18958
  exports.selectTokenEnabled = selectTokenEnabled;
17995
18959
  exports.selectTools = selectTools;
18960
+ exports.sendMessageToParentWebsite = sendMessageToParentWebsite;
18961
+ exports.setCookieForAuth = setCookieForAuth;
17996
18962
  exports.syncAuthToCookies = syncAuthToCookies;
17997
18963
  exports.tenantKeySchema = tenantKeySchema;
17998
18964
  exports.tenantSchema = tenantSchema;
17999
18965
  exports.translatePrompt = translatePrompt;
18966
+ exports.updateFileMetadata = updateFileMetadata;
18967
+ exports.updateFileProgress = updateFileProgress;
18968
+ exports.updateFileRetryCount = updateFileRetryCount;
18969
+ exports.updateFileStatus = updateFileStatus;
18970
+ exports.updateFileUrl = updateFileUrl;
18971
+ exports.updateFileUrlFromWebSocket = updateFileUrlFromWebSocket;
18972
+ exports.uploadToS3 = uploadToS3;
18000
18973
  exports.useAdvancedChat = useAdvancedChat;
18001
18974
  exports.useAuthContext = useAuthContext;
18002
18975
  exports.useAuthProvider = useAuthProvider;
@@ -18014,4 +18987,5 @@ exports.useTimeTracker = useTimeTracker;
18014
18987
  exports.useTimeTrackerNative = useTimeTrackerNative;
18015
18988
  exports.useUserProfileUpdate = useUserProfileUpdate;
18016
18989
  exports.userDataSchema = userDataSchema;
18990
+ exports.validateFile = validateFile;
18017
18991
  //# sourceMappingURL=index.js.map