@iblai/iblai-js 2.3.15 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -97462,6 +97462,14 @@ var analyticsAnalyticsAuditLogStats$3 = {
97462
97462
  colAction: "ACTION",
97463
97463
  colTime: "TIME"
97464
97464
  };
97465
+ var analyticsAnalyticsAgentPicker$3 = {
97466
+ analyticsScope: "Analytics scope",
97467
+ allAgents: "All Agents",
97468
+ agents: "Agents",
97469
+ searchAgents: "Search agents…",
97470
+ noAgentsFound: "No agents found",
97471
+ loading: "Loading…"
97472
+ };
97465
97473
  var analyticsAnalyticsCourseDetail$3 = {
97466
97474
  goBackAriaLabel: "Go back to courses list",
97467
97475
  activeEnrollments: "Active Enrollments",
@@ -103050,6 +103058,7 @@ var en = {
103050
103058
  agentSearchLabels: agentSearchLabels$3,
103051
103059
  analyticsAccessTimeHeatmap: analyticsAccessTimeHeatmap$3,
103052
103060
  analyticsAnalyticsAuditLogStats: analyticsAnalyticsAuditLogStats$3,
103061
+ analyticsAnalyticsAgentPicker: analyticsAnalyticsAgentPicker$3,
103053
103062
  analyticsAnalyticsCourseDetail: analyticsAnalyticsCourseDetail$3,
103054
103063
  analyticsAnalyticsCourses: analyticsAnalyticsCourses$3,
103055
103064
  analyticsAnalyticsFinancialStats: analyticsAnalyticsFinancialStats$3,
@@ -103926,6 +103935,14 @@ var analyticsAnalyticsAuditLogStats$2 = {
103926
103935
  colAction: "ACTION",
103927
103936
  colTime: "HEURE"
103928
103937
  };
103938
+ var analyticsAnalyticsAgentPicker$2 = {
103939
+ analyticsScope: "Portée des analyses",
103940
+ allAgents: "Tous les agents",
103941
+ agents: "Agents",
103942
+ searchAgents: "Rechercher des agents…",
103943
+ noAgentsFound: "Aucun agent trouvé",
103944
+ loading: "Chargement…"
103945
+ };
103929
103946
  var analyticsAnalyticsCourseDetail$2 = {
103930
103947
  goBackAriaLabel: "Retour à la liste des cours",
103931
103948
  activeEnrollments: "Inscriptions actives",
@@ -109514,6 +109531,7 @@ var fr = {
109514
109531
  agentSearchLabels: agentSearchLabels$2,
109515
109532
  analyticsAccessTimeHeatmap: analyticsAccessTimeHeatmap$2,
109516
109533
  analyticsAnalyticsAuditLogStats: analyticsAnalyticsAuditLogStats$2,
109534
+ analyticsAnalyticsAgentPicker: analyticsAnalyticsAgentPicker$2,
109517
109535
  analyticsAnalyticsCourseDetail: analyticsAnalyticsCourseDetail$2,
109518
109536
  analyticsAnalyticsCourses: analyticsAnalyticsCourses$2,
109519
109537
  analyticsAnalyticsFinancialStats: analyticsAnalyticsFinancialStats$2,
@@ -110390,6 +110408,14 @@ var analyticsAnalyticsAuditLogStats$1 = {
110390
110408
  colAction: "ACCIÓN",
110391
110409
  colTime: "HORA"
110392
110410
  };
110411
+ var analyticsAnalyticsAgentPicker$1 = {
110412
+ analyticsScope: "Alcance de analíticas",
110413
+ allAgents: "Todos los agentes",
110414
+ agents: "Agentes",
110415
+ searchAgents: "Buscar agentes…",
110416
+ noAgentsFound: "No se encontraron agentes",
110417
+ loading: "Cargando…"
110418
+ };
110393
110419
  var analyticsAnalyticsCourseDetail$1 = {
110394
110420
  goBackAriaLabel: "Volver a la lista de cursos",
110395
110421
  activeEnrollments: "Inscripciones activas",
@@ -115978,6 +116004,7 @@ var es = {
115978
116004
  agentSearchLabels: agentSearchLabels$1,
115979
116005
  analyticsAccessTimeHeatmap: analyticsAccessTimeHeatmap$1,
115980
116006
  analyticsAnalyticsAuditLogStats: analyticsAnalyticsAuditLogStats$1,
116007
+ analyticsAnalyticsAgentPicker: analyticsAnalyticsAgentPicker$1,
115981
116008
  analyticsAnalyticsCourseDetail: analyticsAnalyticsCourseDetail$1,
115982
116009
  analyticsAnalyticsCourses: analyticsAnalyticsCourses$1,
115983
116010
  analyticsAnalyticsFinancialStats: analyticsAnalyticsFinancialStats$1,
@@ -116854,6 +116881,14 @@ var analyticsAnalyticsAuditLogStats = {
116854
116881
  colAction: "操作",
116855
116882
  colTime: "时间"
116856
116883
  };
116884
+ var analyticsAnalyticsAgentPicker = {
116885
+ analyticsScope: "分析范围",
116886
+ allAgents: "所有智能体",
116887
+ agents: "智能体",
116888
+ searchAgents: "搜索智能体…",
116889
+ noAgentsFound: "未找到智能体",
116890
+ loading: "加载中…"
116891
+ };
116857
116892
  var analyticsAnalyticsCourseDetail = {
116858
116893
  goBackAriaLabel: "返回课程列表",
116859
116894
  activeEnrollments: "活跃注册",
@@ -122442,6 +122477,7 @@ var zh = {
122442
122477
  agentSearchLabels: agentSearchLabels,
122443
122478
  analyticsAccessTimeHeatmap: analyticsAccessTimeHeatmap,
122444
122479
  analyticsAnalyticsAuditLogStats: analyticsAnalyticsAuditLogStats,
122480
+ analyticsAnalyticsAgentPicker: analyticsAnalyticsAgentPicker,
122445
122481
  analyticsAnalyticsCourseDetail: analyticsAnalyticsCourseDetail,
122446
122482
  analyticsAnalyticsCourses: analyticsAnalyticsCourses,
122447
122483
  analyticsAnalyticsFinancialStats: analyticsAnalyticsFinancialStats,
@@ -182347,14 +182383,15 @@ const PAGE_SIZE$8 = 20;
182347
182383
  const SEARCH_DEBOUNCE_MS = 300;
182348
182384
  /**
182349
182385
  * The public application URL on the auth SPA for one form of a platform
182350
- * (`<auth-url>/applications/<platform-key>/<form-id>?app=<spa>`), or null when
182351
- * the auth SPA URL cannot be resolved. `authSpaUrl` (prop) wins; otherwise the
182352
- * runtime-injected env (`window.__ENV__.NEXT_PUBLIC_AUTH_URL`) is used. With no
182353
- * `formId` the link resolves the platform's default form (404 when none). The
182354
- * `app` param carries the SPA the applicant is sent to after submitting;
182355
- * absent/unknown means the mentor SPA.
182356
- */
182357
- function buildApplicationLink(platformKey, formId, authSpaUrl, app) {
182386
+ * (`<auth-url>/applications/<platform-key>/<form-id>?redirect-to=<origin>`), or
182387
+ * null when the auth SPA URL cannot be resolved. `authSpaUrl` (prop) wins;
182388
+ * otherwise the runtime-injected env (`window.__ENV__.NEXT_PUBLIC_AUTH_URL`) is
182389
+ * used. With no `formId` the link resolves the platform's default form (404
182390
+ * when none). The `redirect-to` param carries the origin the applicant is sent
182391
+ * back to after submitting — by default the origin the link is copied from — and
182392
+ * is omitted when no origin can be read (no DOM).
182393
+ */
182394
+ function buildApplicationLink(platformKey, formId, authSpaUrl, redirectTo) {
182358
182395
  var _a, _b;
182359
182396
  const base = (_b = authSpaUrl !== null && authSpaUrl !== void 0 ? authSpaUrl : (typeof window !== 'undefined'
182360
182397
  ? (_a = window.__ENV__) === null || _a === void 0 ? void 0 : _a.NEXT_PUBLIC_AUTH_URL
@@ -182363,7 +182400,8 @@ function buildApplicationLink(platformKey, formId, authSpaUrl, app) {
182363
182400
  return null;
182364
182401
  const root = `${trimTrailingSlashes(base)}/applications/${encodeURIComponent(platformKey)}`;
182365
182402
  const path = formId != null ? `${root}/${encodeURIComponent(String(formId))}` : root;
182366
- return `${path}?app=${encodeURIComponent(app || 'mentor')}`;
182403
+ const target = (typeof window !== 'undefined' ? window.location.origin : undefined);
182404
+ return target ? `${path}?redirect-to=${encodeURIComponent(target)}` : path;
182367
182405
  }
182368
182406
  /**
182369
182407
  * Applications management. Entry view lists the platform's application forms
@@ -182371,7 +182409,7 @@ function buildApplicationLink(platformKey, formId, authSpaUrl, app) {
182371
182409
  * per-form (or all-form) submission pipelines, the submission workspace with
182372
182410
  * per-student decisions, the form/question editor, and the ban list.
182373
182411
  */
182374
- function ApplicationsTab({ platformKey, authSpaUrl, currentSpa, }) {
182412
+ function ApplicationsTab({ platformKey, authSpaUrl, }) {
182375
182413
  const [view, setView] = useState({ name: 'forms' });
182376
182414
  if (view.name === 'editor') {
182377
182415
  return (jsx(QuestionsEditor, { platformKey: platformKey, initialFormId: view.formId, startNew: view.startNew, onBack: () => setView({ name: 'forms' }) }));
@@ -182385,10 +182423,10 @@ function ApplicationsTab({ platformKey, authSpaUrl, currentSpa, }) {
182385
182423
  if (view.name === 'submissions') {
182386
182424
  return (jsx(SubmissionsPipeline, { platformKey: platformKey, form: view.form, onBack: () => setView({ name: 'forms' }), onOpen: (submissionId) => setView({ name: 'detail', submissionId, form: view.form }) }));
182387
182425
  }
182388
- return (jsx(FormsList, { platformKey: platformKey, authSpaUrl: authSpaUrl, currentSpa: currentSpa, onViewSubmissions: (form) => setView({ name: 'submissions', form }), onEditForm: (formId) => setView({ name: 'editor', formId, startNew: false }), onNewForm: () => setView({ name: 'editor', formId: null, startNew: true }), onViewBlocks: () => setView({ name: 'blocks' }) }));
182426
+ return (jsx(FormsList, { platformKey: platformKey, authSpaUrl: authSpaUrl, onViewSubmissions: (form) => setView({ name: 'submissions', form }), onEditForm: (formId) => setView({ name: 'editor', formId, startNew: false }), onNewForm: () => setView({ name: 'editor', formId: null, startNew: true }), onViewBlocks: () => setView({ name: 'blocks' }) }));
182389
182427
  }
182390
182428
  /** The entry view: every application form of the platform, with actions. */
182391
- function FormsList({ platformKey, authSpaUrl, currentSpa, onViewSubmissions, onEditForm, onNewForm, onViewBlocks, }) {
182429
+ function FormsList({ platformKey, authSpaUrl, onViewSubmissions, onEditForm, onNewForm, onViewBlocks, }) {
182392
182430
  const t = useT();
182393
182431
  /** The form id whose link was just copied (transient "Copied" feedback). */
182394
182432
  const [copiedFormId, setCopiedFormId] = useState(null);
@@ -182402,7 +182440,7 @@ function FormsList({ platformKey, authSpaUrl, currentSpa, onViewSubmissions, onE
182402
182440
  const counts = statsCounts(stats);
182403
182441
  const total = Object.values(counts).reduce((sum, n) => sum + n, 0);
182404
182442
  const handleCopyLink = async (form) => {
182405
- const link = buildApplicationLink(platformKey, form.id, authSpaUrl, currentSpa);
182443
+ const link = buildApplicationLink(platformKey, form.id, authSpaUrl);
182406
182444
  if (!link)
182407
182445
  return;
182408
182446
  try {
@@ -182422,7 +182460,7 @@ function FormsList({ platformKey, authSpaUrl, currentSpa, onViewSubmissions, onE
182422
182460
  ? 'bg-blue-50 text-blue-700 border-blue-200 dark:bg-blue-900/30 dark:text-blue-300 dark:border-blue-900'
182423
182461
  : 'bg-gray-100 text-gray-600 border-gray-200 dark:bg-gray-700 dark:text-gray-300 dark:border-gray-600', children: t(form.enabled
182424
182462
  ? 'profileApplicationsTab.formEnabled'
182425
- : 'profileApplicationsTab.formDisabled') }) }), jsx("td", { className: "whitespace-nowrap px-6 py-4 text-right", children: jsxs("div", { className: "flex items-center justify-end gap-1", children: [buildApplicationLink(platformKey, form.id, authSpaUrl, currentSpa) && (jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { asChild: true, children: jsxs(Button$1, { variant: "ghost", className: copiedFormId === form.id
182463
+ : 'profileApplicationsTab.formDisabled') }) }), jsx("td", { className: "whitespace-nowrap px-6 py-4 text-right", children: jsxs("div", { className: "flex items-center justify-end gap-1", children: [buildApplicationLink(platformKey, form.id, authSpaUrl) && (jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { asChild: true, children: jsxs(Button$1, { variant: "ghost", className: copiedFormId === form.id
182426
182464
  ? 'h-8 w-8 p-0 text-blue-600 dark:text-blue-400'
182427
182465
  : 'h-8 w-8 p-0 text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100', onClick: () => handleCopyLink(form), "aria-label": t('profileApplicationsTab.copyFormLink', {
182428
182466
  form: ((_b = form.schema) === null || _b === void 0 ? void 0 : _b.title) ||
@@ -182533,7 +182571,7 @@ const TabDescription = ({ icon, title, children }) => {
182533
182571
  };
182534
182572
  const Admin = ({ tenant, onInviteClick, hasUserTabPermission = false, hasGroupsTabPermission = false, hasRolesTabPermission = false, hasPoliciesTabPermission = false, hasTeamsTabPermission = false, hasAlertsTabPermission = false, hasInviteUserPermission = false, hasCreateTeamPermission = false, onLoadGroupPermissions, rbacPermissions = {}, enableRbac = false, showGradebookTab = false, currentSpa, authSpaUrl, }) => {
182535
182573
  const t = useT();
182536
- return (jsx("div", { className: "border border-gray-200 rounded-lg p-6", children: jsxs(Tabs, { defaultValue: "users", "aria-label": t('profileAdmin.rbacManagementTabsAriaLabel'), children: [jsxs(TabsList, { "aria-label": t('profileAdmin.managementTabsAriaLabel'), className: "max-w-full overflow-x-auto justify-start px-1", children: [hasUserTabPermission && (jsx(TabsTrigger, { value: "users", children: t('profileAdmin.usersTab') })), hasGroupsTabPermission && (jsx(TabsTrigger, { value: "groups", children: t('profileAdmin.groupsTab') })), hasRolesTabPermission && (jsx(TabsTrigger, { value: "roles", children: t('profileAdmin.rolesTab') })), hasPoliciesTabPermission && (jsx(TabsTrigger, { value: "policies", children: t('profileAdmin.policiesTab') })), hasTeamsTabPermission && (jsx(TabsTrigger, { value: "teams", children: t('profileAdmin.teamsTab') })), hasAlertsTabPermission && (jsx(TabsTrigger, { value: "alerts", children: t('profileAdmin.alertsTab') })), jsx(TabsTrigger, { value: "applications", children: t('profileAdmin.applicationsTab') })] }), hasUserTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "users", children: [jsx(TabDescription, { icon: jsx(Users, { className: "w-5 h-5" }), title: t('profileAdmin.usersTab'), children: t('profileAdmin.usersDescription') }), jsx(UsersTab, { tenant: tenant, onInviteClick: onInviteClick, currentSpa: currentSpa, showGradebookTab: showGradebookTab })] })), hasGroupsTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "groups", children: [jsx(TabDescription, { icon: jsx(UsersRound, { className: "w-5 h-5" }), title: t('profileAdmin.groupsTab'), children: t('profileAdmin.groupsDescription') }), jsx(GroupsTab, { tenant: tenant })] })), hasRolesTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "roles", children: [jsx(TabDescription, { icon: jsx(UserCog, { className: "w-5 h-5" }), title: t('profileAdmin.rolesTab'), children: t('profileAdmin.rolesDescription') }), jsx(RolesTab, { tenant: tenant })] })), hasPoliciesTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "policies", children: [jsx(TabDescription, { icon: jsx(ScrollText, { className: "w-5 h-5" }), title: t('profileAdmin.policiesTab'), children: t('profileAdmin.policiesDescription') }), jsx(PoliciesTab, { tenant: tenant })] })), hasTeamsTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "teams", children: [jsx(TabDescription, { icon: jsx(Shield, { className: "w-5 h-5" }), title: t('profileAdmin.teamsTab'), children: t('profileAdmin.teamsDescription') }), jsx(GroupsTab, { tenant: tenant, isTeam: true, onInviteClick: onInviteClick, hasInviteUserPermission: hasInviteUserPermission, hasCreateTeamPermission: hasCreateTeamPermission, onLoadGroupPermissions: onLoadGroupPermissions, rbacPermissions: rbacPermissions, enableRbac: enableRbac })] })), hasAlertsTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "alerts", children: [jsx(TabDescription, { icon: jsx(BellRing, { className: "w-5 h-5" }), title: t('profileAdmin.alertsTab'), children: t('profileAdmin.alertsDescription') }), jsx(AlertsTab, { tenant: tenant })] })), jsxs(TabsContent, { className: "mt-4", value: "applications", children: [jsx(TabDescription, { icon: jsx(ClipboardList, { className: "w-5 h-5" }), title: t('profileAdmin.applicationsTab'), children: t('profileAdmin.applicationsTabDescription') }), jsx(ApplicationsTab, { platformKey: tenant, authSpaUrl: authSpaUrl, currentSpa: currentSpa })] })] }) }));
182574
+ return (jsx("div", { className: "border border-gray-200 rounded-lg p-6", children: jsxs(Tabs, { defaultValue: "users", "aria-label": t('profileAdmin.rbacManagementTabsAriaLabel'), children: [jsxs(TabsList, { "aria-label": t('profileAdmin.managementTabsAriaLabel'), className: "max-w-full overflow-x-auto justify-start px-1", children: [hasUserTabPermission && (jsx(TabsTrigger, { value: "users", children: t('profileAdmin.usersTab') })), hasGroupsTabPermission && (jsx(TabsTrigger, { value: "groups", children: t('profileAdmin.groupsTab') })), hasRolesTabPermission && (jsx(TabsTrigger, { value: "roles", children: t('profileAdmin.rolesTab') })), hasPoliciesTabPermission && (jsx(TabsTrigger, { value: "policies", children: t('profileAdmin.policiesTab') })), hasTeamsTabPermission && (jsx(TabsTrigger, { value: "teams", children: t('profileAdmin.teamsTab') })), hasAlertsTabPermission && (jsx(TabsTrigger, { value: "alerts", children: t('profileAdmin.alertsTab') })), jsx(TabsTrigger, { value: "applications", children: t('profileAdmin.applicationsTab') })] }), hasUserTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "users", children: [jsx(TabDescription, { icon: jsx(Users, { className: "w-5 h-5" }), title: t('profileAdmin.usersTab'), children: t('profileAdmin.usersDescription') }), jsx(UsersTab, { tenant: tenant, onInviteClick: onInviteClick, currentSpa: currentSpa, showGradebookTab: showGradebookTab })] })), hasGroupsTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "groups", children: [jsx(TabDescription, { icon: jsx(UsersRound, { className: "w-5 h-5" }), title: t('profileAdmin.groupsTab'), children: t('profileAdmin.groupsDescription') }), jsx(GroupsTab, { tenant: tenant })] })), hasRolesTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "roles", children: [jsx(TabDescription, { icon: jsx(UserCog, { className: "w-5 h-5" }), title: t('profileAdmin.rolesTab'), children: t('profileAdmin.rolesDescription') }), jsx(RolesTab, { tenant: tenant })] })), hasPoliciesTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "policies", children: [jsx(TabDescription, { icon: jsx(ScrollText, { className: "w-5 h-5" }), title: t('profileAdmin.policiesTab'), children: t('profileAdmin.policiesDescription') }), jsx(PoliciesTab, { tenant: tenant })] })), hasTeamsTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "teams", children: [jsx(TabDescription, { icon: jsx(Shield, { className: "w-5 h-5" }), title: t('profileAdmin.teamsTab'), children: t('profileAdmin.teamsDescription') }), jsx(GroupsTab, { tenant: tenant, isTeam: true, onInviteClick: onInviteClick, hasInviteUserPermission: hasInviteUserPermission, hasCreateTeamPermission: hasCreateTeamPermission, onLoadGroupPermissions: onLoadGroupPermissions, rbacPermissions: rbacPermissions, enableRbac: enableRbac })] })), hasAlertsTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "alerts", children: [jsx(TabDescription, { icon: jsx(BellRing, { className: "w-5 h-5" }), title: t('profileAdmin.alertsTab'), children: t('profileAdmin.alertsDescription') }), jsx(AlertsTab, { tenant: tenant })] })), jsxs(TabsContent, { className: "mt-4", value: "applications", children: [jsx(TabDescription, { icon: jsx(ClipboardList, { className: "w-5 h-5" }), title: t('profileAdmin.applicationsTab'), children: t('profileAdmin.applicationsTabDescription') }), jsx(ApplicationsTab, { platformKey: tenant, authSpaUrl: authSpaUrl })] })] }) }));
182537
182575
  };
182538
182576
 
182539
182577
  function DeleteApiModal$1({ isOpen, onClose, apiKey, tenantKey }) {
@@ -218648,6 +218686,129 @@ function getPayloadConfigFromPayload(config, payload, key) {
218648
218686
 
218649
218687
  React__default.createContext(undefined);
218650
218688
 
218689
+ const AnalyticsScopeContext = createContext({ scopedMentor: null });
218690
+ AnalyticsScopeContext.Provider;
218691
+
218692
+ /**
218693
+ * Core agent search hook — thin wrapper around `useGetAiSearchMentorsQuery`.
218694
+ *
218695
+ * This is the low-level building block. For a higher-level hook that manages
218696
+ * search state, debounce, and pagination controls, use
218697
+ * `useAgentSearchWithPagination`.
218698
+ */
218699
+ function useAgentSearch({ tenantKey, query, limit = 6, offset, starred, featured, category, subjects, llm, types, includeMainPublicMentors, orderDirection, skip = false, }) {
218700
+ var _a, _b, _c;
218701
+ const { data, isLoading, isFetching, refetch } = useGetAiSearchMentorsQuery({
218702
+ platform_key: tenantKey,
218703
+ query: query || undefined,
218704
+ limit,
218705
+ ...(offset !== undefined && { offset }),
218706
+ ...(starred !== undefined && { starred }),
218707
+ ...(featured !== undefined && { featured }),
218708
+ ...(category && { category }),
218709
+ ...(subjects && { subjects }),
218710
+ ...(llm && { llm }),
218711
+ ...(types && { types }),
218712
+ ...(includeMainPublicMentors !== undefined && {
218713
+ include_main_public_mentors: includeMainPublicMentors,
218714
+ }),
218715
+ ...(orderDirection && { order_direction: orderDirection }),
218716
+ }, { skip: skip || !tenantKey });
218717
+ return {
218718
+ agents: ((_a = data === null || data === void 0 ? void 0 : data.results) !== null && _a !== void 0 ? _a : []),
218719
+ facets: data === null || data === void 0 ? void 0 : data.facets,
218720
+ hasMore: !!(data === null || data === void 0 ? void 0 : data.next),
218721
+ totalCount: (_b = data === null || data === void 0 ? void 0 : data.count) !== null && _b !== void 0 ? _b : 0,
218722
+ totalPages: (_c = data === null || data === void 0 ? void 0 : data.total_pages) !== null && _c !== void 0 ? _c : 0,
218723
+ isLoading,
218724
+ isFetching,
218725
+ refetch,
218726
+ };
218727
+ }
218728
+
218729
+ function c$3(e,u,c){var i=this,a=useRef(null),o=useRef(0),f=useRef(null),l=useRef([]),v=useRef(),m=useRef(),d=useRef(e),g=useRef(true);d.current=e;var p="undefined"!=typeof window,w=!u&&0!==u&&p;if("function"!=typeof e)throw new TypeError("Expected a function");u=+u||0;var s=!!(c=c||{}).leading,x=!("trailing"in c)||!!c.trailing,h="maxWait"in c,y="debounceOnServer"in c&&!!c.debounceOnServer,F=h?Math.max(+c.maxWait||0,u):null;useEffect(function(){return g.current=true,function(){g.current=false;}},[]);var A=useMemo(function(){var r=function(r){var n=l.current,t=v.current;return l.current=v.current=null,o.current=r,m.current=d.current.apply(t,n)},n=function(r,n){w&&cancelAnimationFrame(f.current),f.current=w?requestAnimationFrame(r):setTimeout(r,n);},t=function(r){if(!g.current)return false;var n=r-a.current;return !a.current||n>=u||n<0||h&&r-o.current>=F},e=function(n){return f.current=null,x&&l.current?r(n):(l.current=v.current=null,m.current)},c=function r(){var c=Date.now();if(t(c))return e(c);if(g.current){var i=u-(c-a.current),f=h?Math.min(i,F-(c-o.current)):i;n(r,f);}},A=function(){if(p||y){var e=Date.now(),d=t(e);if(l.current=[].slice.call(arguments),v.current=i,a.current=e,d){if(!f.current&&g.current)return o.current=a.current,n(c,u),s?r(a.current):m.current;if(h)return n(c,u),r(a.current)}return f.current||n(c,u),m.current}};return A.cancel=function(){f.current&&(w?cancelAnimationFrame(f.current):clearTimeout(f.current)),o.current=0,l.current=a.current=v.current=f.current=null;},A.isPending=function(){return !!f.current},A.flush=function(){return f.current?e(Date.now()):m.current},A},[s,h,u,F,x,w,p,y]);return A}function i$8(r,n){return r===n}function a$3(n,t,a){var o=i$8,f=useRef(n),l=useState({})[1],v=c$3(useCallback(function(r){f.current=r,l({});},[l]),t,a),m=useRef(n);return o(m.current,n)||(v(n),m.current=n),[f.current,v]}
218730
+
218731
+ /**
218732
+ * Higher-level agent search hook that manages search state, debounce, and
218733
+ * pagination controls on top of `useAgentSearch`.
218734
+ *
218735
+ * Use this for simple list/table views (MyMentorsModal, SettingsModal).
218736
+ * For the full explore page with sections, use `useAgentSearch` directly.
218737
+ */
218738
+ function useAgentSearchWithPagination({ itemsPerPage = 6, paginationMode = 'paginated', debounceMs = 500, ...queryConfig }) {
218739
+ const [searchQuery, setSearchQuery] = React__default.useState('');
218740
+ const [debouncedQuery] = a$3(searchQuery, debounceMs);
218741
+ const [currentPage, setCurrentPage] = React__default.useState(1);
218742
+ const [infiniteLimit, setInfiniteLimit] = React__default.useState(itemsPerPage);
218743
+ // Reset pagination when search changes
218744
+ React__default.useEffect(() => {
218745
+ setCurrentPage(1);
218746
+ setInfiniteLimit(itemsPerPage);
218747
+ }, [debouncedQuery, itemsPerPage]);
218748
+ const isPaginated = paginationMode === 'paginated';
218749
+ const result = useAgentSearch({
218750
+ ...queryConfig,
218751
+ query: debouncedQuery,
218752
+ limit: isPaginated ? itemsPerPage : infiniteLimit,
218753
+ offset: isPaginated ? (currentPage - 1) * itemsPerPage : undefined,
218754
+ });
218755
+ const totalPages = Math.ceil(result.totalCount / itemsPerPage);
218756
+ const handlePageChange = React__default.useCallback((page) => {
218757
+ setCurrentPage(page);
218758
+ }, []);
218759
+ const loadMore = React__default.useCallback(() => {
218760
+ setInfiniteLimit((prev) => prev + itemsPerPage);
218761
+ }, [itemsPerPage]);
218762
+ return {
218763
+ ...result,
218764
+ searchQuery,
218765
+ setSearchQuery,
218766
+ debouncedQuery,
218767
+ currentPage,
218768
+ totalPages,
218769
+ handlePageChange,
218770
+ loadMore,
218771
+ };
218772
+ }
218773
+
218774
+ /**
218775
+ * Hook for starring / un-starring agents.
218776
+ *
218777
+ * Extracted so the star logic can be shared by any component that renders
218778
+ * agent cards with a favorite toggle.
218779
+ */
218780
+ function useAgentStar({ tenantKey, username, onUnauthenticatedAction, }) {
218781
+ const [starAgent] = useStarMentorMutation();
218782
+ const [unstarAgent] = useUnstarMentorMutation();
218783
+ const [togglingAgentId, setTogglingAgentId] = React__default.useState(null);
218784
+ const toggleFavorite = React__default.useCallback(async (agent, event) => {
218785
+ event.stopPropagation();
218786
+ if (!username) {
218787
+ onUnauthenticatedAction === null || onUnauthenticatedAction === void 0 ? void 0 : onUnauthenticatedAction();
218788
+ return;
218789
+ }
218790
+ if (!tenantKey)
218791
+ return;
218792
+ setTogglingAgentId(String(agent.id));
218793
+ try {
218794
+ const mutation = agent.starred ? unstarAgent : starAgent;
218795
+ await mutation({
218796
+ org: tenantKey,
218797
+ // @ts-expect-error userId param type mismatch in data-layer
218798
+ userId: username,
218799
+ mentor: agent.unique_id || '',
218800
+ }).unwrap();
218801
+ }
218802
+ catch (error) {
218803
+ console.error('Error toggling favorite:', error);
218804
+ }
218805
+ finally {
218806
+ setTogglingAgentId(null);
218807
+ }
218808
+ }, [username, tenantKey, starAgent, unstarAgent, onUnauthenticatedAction]);
218809
+ return { toggleFavorite, togglingAgentId };
218810
+ }
218811
+
218651
218812
  Array.from({ length: 24 }, (_, i) => i);
218652
218813
 
218653
218814
  /**
@@ -253184,126 +253345,6 @@ function SheetDescription({ className, ...props }) {
253184
253345
  return (jsx(DialogPrimitive.Description, { "data-slot": "sheet-description", className: cn('text-muted-foreground text-sm', className), ...props }));
253185
253346
  }
253186
253347
 
253187
- /**
253188
- * Core agent search hook — thin wrapper around `useGetAiSearchMentorsQuery`.
253189
- *
253190
- * This is the low-level building block. For a higher-level hook that manages
253191
- * search state, debounce, and pagination controls, use
253192
- * `useAgentSearchWithPagination`.
253193
- */
253194
- function useAgentSearch({ tenantKey, query, limit = 6, offset, starred, featured, category, subjects, llm, types, includeMainPublicMentors, orderDirection, skip = false, }) {
253195
- var _a, _b, _c;
253196
- const { data, isLoading, isFetching, refetch } = useGetAiSearchMentorsQuery({
253197
- platform_key: tenantKey,
253198
- query: query || undefined,
253199
- limit,
253200
- ...(offset !== undefined && { offset }),
253201
- ...(starred !== undefined && { starred }),
253202
- ...(featured !== undefined && { featured }),
253203
- ...(category && { category }),
253204
- ...(subjects && { subjects }),
253205
- ...(llm && { llm }),
253206
- ...(types && { types }),
253207
- ...(includeMainPublicMentors !== undefined && {
253208
- include_main_public_mentors: includeMainPublicMentors,
253209
- }),
253210
- ...(orderDirection && { order_direction: orderDirection }),
253211
- }, { skip: skip || !tenantKey });
253212
- return {
253213
- agents: ((_a = data === null || data === void 0 ? void 0 : data.results) !== null && _a !== void 0 ? _a : []),
253214
- facets: data === null || data === void 0 ? void 0 : data.facets,
253215
- hasMore: !!(data === null || data === void 0 ? void 0 : data.next),
253216
- totalCount: (_b = data === null || data === void 0 ? void 0 : data.count) !== null && _b !== void 0 ? _b : 0,
253217
- totalPages: (_c = data === null || data === void 0 ? void 0 : data.total_pages) !== null && _c !== void 0 ? _c : 0,
253218
- isLoading,
253219
- isFetching,
253220
- refetch,
253221
- };
253222
- }
253223
-
253224
- function c$3(e,u,c){var i=this,a=useRef(null),o=useRef(0),f=useRef(null),l=useRef([]),v=useRef(),m=useRef(),d=useRef(e),g=useRef(true);d.current=e;var p="undefined"!=typeof window,w=!u&&0!==u&&p;if("function"!=typeof e)throw new TypeError("Expected a function");u=+u||0;var s=!!(c=c||{}).leading,x=!("trailing"in c)||!!c.trailing,h="maxWait"in c,y="debounceOnServer"in c&&!!c.debounceOnServer,F=h?Math.max(+c.maxWait||0,u):null;useEffect(function(){return g.current=true,function(){g.current=false;}},[]);var A=useMemo(function(){var r=function(r){var n=l.current,t=v.current;return l.current=v.current=null,o.current=r,m.current=d.current.apply(t,n)},n=function(r,n){w&&cancelAnimationFrame(f.current),f.current=w?requestAnimationFrame(r):setTimeout(r,n);},t=function(r){if(!g.current)return false;var n=r-a.current;return !a.current||n>=u||n<0||h&&r-o.current>=F},e=function(n){return f.current=null,x&&l.current?r(n):(l.current=v.current=null,m.current)},c=function r(){var c=Date.now();if(t(c))return e(c);if(g.current){var i=u-(c-a.current),f=h?Math.min(i,F-(c-o.current)):i;n(r,f);}},A=function(){if(p||y){var e=Date.now(),d=t(e);if(l.current=[].slice.call(arguments),v.current=i,a.current=e,d){if(!f.current&&g.current)return o.current=a.current,n(c,u),s?r(a.current):m.current;if(h)return n(c,u),r(a.current)}return f.current||n(c,u),m.current}};return A.cancel=function(){f.current&&(w?cancelAnimationFrame(f.current):clearTimeout(f.current)),o.current=0,l.current=a.current=v.current=f.current=null;},A.isPending=function(){return !!f.current},A.flush=function(){return f.current?e(Date.now()):m.current},A},[s,h,u,F,x,w,p,y]);return A}function i$8(r,n){return r===n}function a$3(n,t,a){var o=i$8,f=useRef(n),l=useState({})[1],v=c$3(useCallback(function(r){f.current=r,l({});},[l]),t,a),m=useRef(n);return o(m.current,n)||(v(n),m.current=n),[f.current,v]}
253225
-
253226
- /**
253227
- * Higher-level agent search hook that manages search state, debounce, and
253228
- * pagination controls on top of `useAgentSearch`.
253229
- *
253230
- * Use this for simple list/table views (MyMentorsModal, SettingsModal).
253231
- * For the full explore page with sections, use `useAgentSearch` directly.
253232
- */
253233
- function useAgentSearchWithPagination({ itemsPerPage = 6, paginationMode = 'paginated', debounceMs = 500, ...queryConfig }) {
253234
- const [searchQuery, setSearchQuery] = React__default.useState('');
253235
- const [debouncedQuery] = a$3(searchQuery, debounceMs);
253236
- const [currentPage, setCurrentPage] = React__default.useState(1);
253237
- const [infiniteLimit, setInfiniteLimit] = React__default.useState(itemsPerPage);
253238
- // Reset pagination when search changes
253239
- React__default.useEffect(() => {
253240
- setCurrentPage(1);
253241
- setInfiniteLimit(itemsPerPage);
253242
- }, [debouncedQuery, itemsPerPage]);
253243
- const isPaginated = paginationMode === 'paginated';
253244
- const result = useAgentSearch({
253245
- ...queryConfig,
253246
- query: debouncedQuery,
253247
- limit: isPaginated ? itemsPerPage : infiniteLimit,
253248
- offset: isPaginated ? (currentPage - 1) * itemsPerPage : undefined,
253249
- });
253250
- const totalPages = Math.ceil(result.totalCount / itemsPerPage);
253251
- const handlePageChange = React__default.useCallback((page) => {
253252
- setCurrentPage(page);
253253
- }, []);
253254
- const loadMore = React__default.useCallback(() => {
253255
- setInfiniteLimit((prev) => prev + itemsPerPage);
253256
- }, [itemsPerPage]);
253257
- return {
253258
- ...result,
253259
- searchQuery,
253260
- setSearchQuery,
253261
- debouncedQuery,
253262
- currentPage,
253263
- totalPages,
253264
- handlePageChange,
253265
- loadMore,
253266
- };
253267
- }
253268
-
253269
- /**
253270
- * Hook for starring / un-starring agents.
253271
- *
253272
- * Extracted so the star logic can be shared by any component that renders
253273
- * agent cards with a favorite toggle.
253274
- */
253275
- function useAgentStar({ tenantKey, username, onUnauthenticatedAction, }) {
253276
- const [starAgent] = useStarMentorMutation();
253277
- const [unstarAgent] = useUnstarMentorMutation();
253278
- const [togglingAgentId, setTogglingAgentId] = React__default.useState(null);
253279
- const toggleFavorite = React__default.useCallback(async (agent, event) => {
253280
- event.stopPropagation();
253281
- if (!username) {
253282
- onUnauthenticatedAction === null || onUnauthenticatedAction === void 0 ? void 0 : onUnauthenticatedAction();
253283
- return;
253284
- }
253285
- if (!tenantKey)
253286
- return;
253287
- setTogglingAgentId(String(agent.id));
253288
- try {
253289
- const mutation = agent.starred ? unstarAgent : starAgent;
253290
- await mutation({
253291
- org: tenantKey,
253292
- // @ts-expect-error userId param type mismatch in data-layer
253293
- userId: username,
253294
- mentor: agent.unique_id || '',
253295
- }).unwrap();
253296
- }
253297
- catch (error) {
253298
- console.error('Error toggling favorite:', error);
253299
- }
253300
- finally {
253301
- setTogglingAgentId(null);
253302
- }
253303
- }, [username, tenantKey, starAgent, unstarAgent, onUnauthenticatedAction]);
253304
- return { toggleFavorite, togglingAgentId };
253305
- }
253306
-
253307
253348
  function MentorSelectionGrid({ selectedMentorIds, onMentorSelect, searchQuery, onSearchChange, tenantKey, itemsPerPage = 8, showSearch = true, minHeight = '400px', }) {
253308
253349
  const t = useT();
253309
253350
  const { agents: mentors, isLoading: isMentorsLoading, isFetching: isMentorsFetching, currentPage, totalPages, setSearchQuery: setMentorSearch, handlePageChange, } = useAgentSearchWithPagination({ tenantKey, itemsPerPage });
@@ -267936,6 +267977,13 @@ function ConnectorManagementContent({ tenantKey, username, mentorId, rbacPermiss
267936
267977
  }).unwrap();
267937
267978
  if (!result.auth_url)
267938
267979
  throw new Error('No authorization URL returned');
267980
+ // Bail if the flow was already torn down while we awaited the auth URL
267981
+ // (e.g. the component unmounted). `cleanup` has run and been dropped
267982
+ // from `oauthCleanupsRef`, so anything registered past this point —
267983
+ // listeners, intervals, timers — would leak with nothing left to
267984
+ // remove it.
267985
+ if (cleanedUp)
267986
+ return;
267939
267987
  const popup = window.open(result.auth_url, '_blank');
267940
267988
  // Create connection using helper function
267941
267989
  const doCreateConnection = async (connectedServiceId) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iblai/iblai-js",
3
- "version": "2.3.15",
3
+ "version": "2.4.0",
4
4
  "description": "Unified JavaScript SDK for IBL.ai — re-exports data-layer, web-containers, and web-utils under a single package",
5
5
  "type": "module",
6
6
  "engines": {
@@ -77,9 +77,9 @@
77
77
  "dotenv": "16.6.1",
78
78
  "winston": "3.19.0",
79
79
  "@iblai/data-layer": "1.12.5",
80
- "@iblai/mcp": "1.8.13",
81
- "@iblai/web-containers": "1.16.11",
82
- "@iblai/web-utils": "2.1.13"
80
+ "@iblai/web-containers": "1.17.0",
81
+ "@iblai/web-utils": "2.1.13",
82
+ "@iblai/mcp": "1.9.0"
83
83
  },
84
84
  "peerDependencies": {
85
85
  "@iblai/iblai-api": "4.166.0-ai",