@iblai/iblai-js 2.3.16 → 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.
@@ -60579,6 +60579,14 @@ var analyticsAnalyticsAuditLogStats$3 = {
60579
60579
  colAction: "ACTION",
60580
60580
  colTime: "TIME"
60581
60581
  };
60582
+ var analyticsAnalyticsAgentPicker$3 = {
60583
+ analyticsScope: "Analytics scope",
60584
+ allAgents: "All Agents",
60585
+ agents: "Agents",
60586
+ searchAgents: "Search agents…",
60587
+ noAgentsFound: "No agents found",
60588
+ loading: "Loading…"
60589
+ };
60582
60590
  var analyticsAnalyticsCourseDetail$3 = {
60583
60591
  goBackAriaLabel: "Go back to courses list",
60584
60592
  activeEnrollments: "Active Enrollments",
@@ -66167,6 +66175,7 @@ var en = {
66167
66175
  agentSearchLabels: agentSearchLabels$3,
66168
66176
  analyticsAccessTimeHeatmap: analyticsAccessTimeHeatmap$3,
66169
66177
  analyticsAnalyticsAuditLogStats: analyticsAnalyticsAuditLogStats$3,
66178
+ analyticsAnalyticsAgentPicker: analyticsAnalyticsAgentPicker$3,
66170
66179
  analyticsAnalyticsCourseDetail: analyticsAnalyticsCourseDetail$3,
66171
66180
  analyticsAnalyticsCourses: analyticsAnalyticsCourses$3,
66172
66181
  analyticsAnalyticsFinancialStats: analyticsAnalyticsFinancialStats$3,
@@ -67043,6 +67052,14 @@ var analyticsAnalyticsAuditLogStats$2 = {
67043
67052
  colAction: "ACTION",
67044
67053
  colTime: "HEURE"
67045
67054
  };
67055
+ var analyticsAnalyticsAgentPicker$2 = {
67056
+ analyticsScope: "Portée des analyses",
67057
+ allAgents: "Tous les agents",
67058
+ agents: "Agents",
67059
+ searchAgents: "Rechercher des agents…",
67060
+ noAgentsFound: "Aucun agent trouvé",
67061
+ loading: "Chargement…"
67062
+ };
67046
67063
  var analyticsAnalyticsCourseDetail$2 = {
67047
67064
  goBackAriaLabel: "Retour à la liste des cours",
67048
67065
  activeEnrollments: "Inscriptions actives",
@@ -72631,6 +72648,7 @@ var fr = {
72631
72648
  agentSearchLabels: agentSearchLabels$2,
72632
72649
  analyticsAccessTimeHeatmap: analyticsAccessTimeHeatmap$2,
72633
72650
  analyticsAnalyticsAuditLogStats: analyticsAnalyticsAuditLogStats$2,
72651
+ analyticsAnalyticsAgentPicker: analyticsAnalyticsAgentPicker$2,
72634
72652
  analyticsAnalyticsCourseDetail: analyticsAnalyticsCourseDetail$2,
72635
72653
  analyticsAnalyticsCourses: analyticsAnalyticsCourses$2,
72636
72654
  analyticsAnalyticsFinancialStats: analyticsAnalyticsFinancialStats$2,
@@ -73507,6 +73525,14 @@ var analyticsAnalyticsAuditLogStats$1 = {
73507
73525
  colAction: "ACCIÓN",
73508
73526
  colTime: "HORA"
73509
73527
  };
73528
+ var analyticsAnalyticsAgentPicker$1 = {
73529
+ analyticsScope: "Alcance de analíticas",
73530
+ allAgents: "Todos los agentes",
73531
+ agents: "Agentes",
73532
+ searchAgents: "Buscar agentes…",
73533
+ noAgentsFound: "No se encontraron agentes",
73534
+ loading: "Cargando…"
73535
+ };
73510
73536
  var analyticsAnalyticsCourseDetail$1 = {
73511
73537
  goBackAriaLabel: "Volver a la lista de cursos",
73512
73538
  activeEnrollments: "Inscripciones activas",
@@ -79095,6 +79121,7 @@ var es = {
79095
79121
  agentSearchLabels: agentSearchLabels$1,
79096
79122
  analyticsAccessTimeHeatmap: analyticsAccessTimeHeatmap$1,
79097
79123
  analyticsAnalyticsAuditLogStats: analyticsAnalyticsAuditLogStats$1,
79124
+ analyticsAnalyticsAgentPicker: analyticsAnalyticsAgentPicker$1,
79098
79125
  analyticsAnalyticsCourseDetail: analyticsAnalyticsCourseDetail$1,
79099
79126
  analyticsAnalyticsCourses: analyticsAnalyticsCourses$1,
79100
79127
  analyticsAnalyticsFinancialStats: analyticsAnalyticsFinancialStats$1,
@@ -79971,6 +79998,14 @@ var analyticsAnalyticsAuditLogStats = {
79971
79998
  colAction: "操作",
79972
79999
  colTime: "时间"
79973
80000
  };
80001
+ var analyticsAnalyticsAgentPicker = {
80002
+ analyticsScope: "分析范围",
80003
+ allAgents: "所有智能体",
80004
+ agents: "智能体",
80005
+ searchAgents: "搜索智能体…",
80006
+ noAgentsFound: "未找到智能体",
80007
+ loading: "加载中…"
80008
+ };
79974
80009
  var analyticsAnalyticsCourseDetail = {
79975
80010
  goBackAriaLabel: "返回课程列表",
79976
80011
  activeEnrollments: "活跃注册",
@@ -85559,6 +85594,7 @@ var zh = {
85559
85594
  agentSearchLabels: agentSearchLabels,
85560
85595
  analyticsAccessTimeHeatmap: analyticsAccessTimeHeatmap,
85561
85596
  analyticsAnalyticsAuditLogStats: analyticsAnalyticsAuditLogStats,
85597
+ analyticsAnalyticsAgentPicker: analyticsAnalyticsAgentPicker,
85562
85598
  analyticsAnalyticsCourseDetail: analyticsAnalyticsCourseDetail,
85563
85599
  analyticsAnalyticsCourses: analyticsAnalyticsCourses,
85564
85600
  analyticsAnalyticsFinancialStats: analyticsAnalyticsFinancialStats,
@@ -148067,7 +148103,7 @@ function BlocksView({ platformKey, onBack, }) {
148067
148103
 
148068
148104
  const FILTER_ORDER = ['all', ...APPLICATION_STATUSES];
148069
148105
  const PAGE_SIZE$3 = 20;
148070
- const SEARCH_DEBOUNCE_MS$1 = 300;
148106
+ const SEARCH_DEBOUNCE_MS$2 = 300;
148071
148107
  /**
148072
148108
  * The public application URL on the auth SPA for one form of a platform
148073
148109
  * (`<auth-url>/applications/<platform-key>/<form-id>?redirect-to=<origin>`), or
@@ -148178,7 +148214,7 @@ function SubmissionsPipeline({ platformKey, form, onBack, onOpen, }) {
148178
148214
  const timer = setTimeout(() => {
148179
148215
  setDebouncedSearch(search.trim());
148180
148216
  setDebouncedCandidateFilter(candidateFilter.trim());
148181
- }, SEARCH_DEBOUNCE_MS$1);
148217
+ }, SEARCH_DEBOUNCE_MS$2);
148182
148218
  return () => clearTimeout(timer);
148183
148219
  }, [search, candidateFilter]);
148184
148220
  // New filters restart paging.
@@ -152915,7 +152951,7 @@ function SearchableMultiSelect({ items, selectedItems, onSelectionChange, search
152915
152951
  }) }))] }));
152916
152952
  }
152917
152953
 
152918
- function useDebouncedValue$4(value, delay) {
152954
+ function useDebouncedValue$5(value, delay) {
152919
152955
  const [debouncedValue, setDebouncedValue] = React__default.useState(value);
152920
152956
  React__default.useEffect(() => {
152921
152957
  const timer = window.setTimeout(() => setDebouncedValue(value), delay);
@@ -152960,8 +152996,8 @@ function TokenPolicyFields({ tenantKey, mode, onModeChange, policies, onPolicies
152960
152996
  const t = useT();
152961
152997
  const [policySearch, setPolicySearch] = React__default.useState('');
152962
152998
  const [groupSearch, setGroupSearch] = React__default.useState('');
152963
- const debouncedPolicySearch = useDebouncedValue$4(policySearch, RBAC_SEARCH_DEBOUNCE_MS);
152964
- const debouncedGroupSearch = useDebouncedValue$4(groupSearch, RBAC_SEARCH_DEBOUNCE_MS);
152999
+ const debouncedPolicySearch = useDebouncedValue$5(policySearch, RBAC_SEARCH_DEBOUNCE_MS);
153000
+ const debouncedGroupSearch = useDebouncedValue$5(groupSearch, RBAC_SEARCH_DEBOUNCE_MS);
152965
153001
  const canWriteMode = canWriteField(fieldPermissions, 'mode');
152966
153002
  const canWritePolicies = canWriteField(fieldPermissions, 'policies_to_add') ||
152967
153003
  canWriteField(fieldPermissions, 'policies_to_remove');
@@ -185842,7 +185878,7 @@ function PolicyConfigDialog({ open, onOpenChange, config, onSave, }) {
185842
185878
  return (jsx(Dialog, { open: open, onOpenChange: handleOpenChange, children: jsxs(DialogContent, { className: "sm:max-w-md", "aria-describedby": "policy-config-description", children: [jsxs(DialogHeader, { children: [jsx(DialogTitle, { children: t('componentsPolicyConfigDialog.title') }), jsx(DialogDescription, { id: "policy-config-description", children: t('componentsPolicyConfigDialog.description') })] }), jsxs("div", { className: "space-y-4", children: [jsxs("div", { children: [jsx(Label$2, { htmlFor: "policy-config-role-name", className: "text-sm font-medium text-gray-700", children: t('componentsPolicyConfigDialog.roleName') }), jsx(Input, { id: "policy-config-role-name", value: (_a = draft === null || draft === void 0 ? void 0 : draft.role_name) !== null && _a !== void 0 ? _a : '', disabled: true, className: "bg-gray-50" })] }), jsxs("div", { className: "flex items-center space-x-2", children: [jsx(Checkbox, { id: "policy-config-enabled", checked: (_b = draft === null || draft === void 0 ? void 0 : draft.enabled) !== null && _b !== void 0 ? _b : true, onCheckedChange: (checked) => updateDraft({ enabled: checked === true }) }), jsx(Label$2, { htmlFor: "policy-config-enabled", className: "text-sm font-medium text-gray-700 cursor-pointer", children: t('componentsPolicyConfigDialog.enabled') })] }), jsxs("div", { className: "flex items-center space-x-2", children: [jsx(Checkbox, { id: "policy-config-notify-assignment", checked: (_c = draft === null || draft === void 0 ? void 0 : draft.notify_on_assignment) !== null && _c !== void 0 ? _c : true, onCheckedChange: (checked) => updateDraft({ notify_on_assignment: checked === true }) }), jsx(Label$2, { htmlFor: "policy-config-notify-assignment", className: "text-sm font-medium text-gray-700 cursor-pointer", children: t('componentsPolicyConfigDialog.notifyOnAssignment') })] }), jsxs("div", { className: "flex items-center space-x-2", children: [jsx(Checkbox, { id: "policy-config-notify-removal", checked: (_d = draft === null || draft === void 0 ? void 0 : draft.notify_on_removal) !== null && _d !== void 0 ? _d : true, onCheckedChange: (checked) => updateDraft({ notify_on_removal: checked === true }) }), jsx(Label$2, { htmlFor: "policy-config-notify-removal", className: "text-sm font-medium text-gray-700 cursor-pointer", children: t('componentsPolicyConfigDialog.notifyOnRemoval') })] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "policy-config-subject", className: "text-sm font-medium text-gray-700", children: t('componentsPolicyConfigDialog.subject') }), jsx(Textarea, { id: "policy-config-subject", value: (_e = draft === null || draft === void 0 ? void 0 : draft.subject) !== null && _e !== void 0 ? _e : '', onChange: (event) => updateDraft({ subject: event.target.value }), placeholder: t('componentsPolicyConfigDialog.subjectPlaceholder'), rows: 3 }), jsx("p", { className: "text-xs text-gray-500", children: t('componentsPolicyConfigDialog.subjectHint') })] })] }), jsxs(DialogFooter, { className: "pt-2", children: [jsx(Button$1, { variant: "outline", onClick: () => onOpenChange(false), children: t('componentsPolicyConfigDialog.cancel') }), jsx(Button$1, { className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] hover:opacity-90 text-white", onClick: handleSave, disabled: !config, children: t('componentsPolicyConfigDialog.saveConfiguration') })] })] }) }));
185843
185879
  }
185844
185880
 
185845
- function useDebouncedValue$3(value, delay) {
185881
+ function useDebouncedValue$4(value, delay) {
185846
185882
  const [debouncedValue, setDebouncedValue] = useState(value);
185847
185883
  useEffect(() => {
185848
185884
  const timer = window.setTimeout(() => setDebouncedValue(value), delay);
@@ -185871,7 +185907,7 @@ function ProactiveSettingsSection({ platformKey, username, isSaving, userLocalTi
185871
185907
  const [isPromptDialogOpen, setIsPromptDialogOpen] = useState(false);
185872
185908
  const customIntervalErrorId = 'proactive-custom-interval-error';
185873
185909
  const executionTimeErrorId = 'proactive-execution-time-error';
185874
- const debouncedMentorSearch = useDebouncedValue$3(mentorSearch, 300);
185910
+ const debouncedMentorSearch = useDebouncedValue$4(mentorSearch, 300);
185875
185911
  const showUseLocalTimezone = periodicTimezone !== userLocalTimezone;
185876
185912
  const shouldFetchMentors = Boolean(platformKey) && Boolean(username);
185877
185913
  const { data: mentorsResponse, isLoading: isMentorsLoading } = useGetMentorsQuery({
@@ -185968,7 +186004,7 @@ function ProactiveSettingsSection({ platformKey, username, isSaving, userLocalTi
185968
186004
  }) })] })] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "periodic-execution-time", className: "text-sm font-medium text-gray-700", children: t('componentsProactiveSettingsSection.executionTimeLabel') }), jsx(Input, { id: "periodic-execution-time", type: "time", value: periodicExecutionTime, onChange: (event) => onExecutionTimeChange(event.target.value), disabled: isSaving, "aria-invalid": isExecutionTimeMissing, "aria-describedby": isExecutionTimeMissing ? executionTimeErrorId : undefined }), renderTimezoneNotice(t('componentsProactiveSettingsSection.chooseWhenNotice'))] })] })), periodicFrequency !== 'CUSTOM' && (jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { htmlFor: "periodic-execution-time", className: "text-sm font-medium text-gray-700", children: t('componentsProactiveSettingsSection.executionTimeLabel') }), jsx(Input, { id: "periodic-execution-time", type: "time", value: periodicExecutionTime, onChange: (event) => onExecutionTimeChange(event.target.value), disabled: isSaving }), renderTimezoneNotice(t('componentsProactiveSettingsSection.optionalChooseWhenNotice'))] })), isProactiveInvalid && (jsxs("div", { className: "space-y-1", "aria-live": "polite", children: [isCustomIntervalMissing && (jsx("p", { id: customIntervalErrorId, className: "text-sm text-red-600", role: "alert", children: t('componentsProactiveSettingsSection.customIntervalError') })), isExecutionTimeMissing && (jsx("p", { id: executionTimeErrorId, className: "text-sm text-red-600", role: "alert", children: t('componentsProactiveSettingsSection.executionTimeError') }))] })), jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", htmlFor: "periodic-mentors", children: t('componentsProactiveSettingsSection.periodicAgentsLabel') }), jsx(SearchableMultiSelect, { items: mentorOptions, selectedItems: selectedMentors, onSelectionChange: handleMentorSelectionChange, searchQuery: mentorSearch, onSearchChange: setMentorSearch, isLoading: isMentorsLoading, placeholder: t('componentsProactiveSettingsSection.searchAgentsPlaceholder'), getItemValue: (mentor) => mentor.unique_id, getItemLabel: (mentor) => mentor.name ? `${mentor.name} (${mentor.unique_id})` : mentor.unique_id, onSelectedItemAction: handleEditMentorPrompt, selectedItemActionIcon: jsx(SquarePen, { className: "h-3 w-3", "aria-hidden": "true" }), selectedItemActionAriaLabel: t('componentsProactiveSettingsSection.editAgentPromptAriaLabel'), inputId: "periodic-mentors", ariaDescribedBy: "periodic-mentors-help", className: "max-w-full" }), jsx("p", { id: "periodic-mentors-help", className: "text-xs text-gray-500", children: t('componentsProactiveSettingsSection.periodicAgentsHelp') })] })] }), jsx(MentorPromptDialog, { open: isPromptDialogOpen, onOpenChange: setIsPromptDialogOpen, mentor: activePromptMentor, initialPrompt: activePromptMentor ? ((_b = mentorPrompts[activePromptMentor.id]) !== null && _b !== void 0 ? _b : '') : '', onSave: handlePromptSave })] }));
185969
186005
  }
185970
186006
 
185971
- function useDebouncedValue$2(value, delay) {
186007
+ function useDebouncedValue$3(value, delay) {
185972
186008
  const [debouncedValue, setDebouncedValue] = useState(value);
185973
186009
  useEffect(() => {
185974
186010
  const timer = window.setTimeout(() => setDebouncedValue(value), delay);
@@ -186000,7 +186036,7 @@ function PolicyAssignmentSection({ platformKey, isSaving, notifyOnAssignment, on
186000
186036
  const [isPolicyConfigDialogOpen, setIsPolicyConfigDialogOpen] = useState(false);
186001
186037
  // Track the last initialized data to detect when new data arrives
186002
186038
  const lastInitializedRef = useRef('');
186003
- const debouncedPolicySearch = useDebouncedValue$2(policySearch, 300);
186039
+ const debouncedPolicySearch = useDebouncedValue$3(policySearch, 300);
186004
186040
  const shouldFetchPolicies = Boolean(platformKey);
186005
186041
  const { data: policiesResponse, isLoading: isPoliciesLoading } = useGetRbacPoliciesQuery({ platformKey }, { skip: !shouldFetchPolicies });
186006
186042
  const policyOptions = useMemo(() => {
@@ -186095,7 +186131,7 @@ function PolicyAssignmentSection({ platformKey, isSaving, notifyOnAssignment, on
186095
186131
  return (jsxs(Fragment$1, { children: [jsxs("div", { className: "space-y-4 border-t border-gray-200 pt-4", children: [jsxs("div", { className: "space-y-1", children: [jsx("h3", { className: "text-sm font-semibold text-gray-900", children: t('componentsPolicyAssignmentSection.sectionTitle') }), jsx("p", { className: "text-xs text-gray-500", children: t('componentsPolicyAssignmentSection.sectionDescription') })] }), jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [jsxs("div", { className: "flex items-center space-x-2", children: [jsx(Checkbox, { id: "policy-notify-assignment", checked: notifyOnAssignment, onCheckedChange: (checked) => onNotifyOnAssignmentChange(checked === true), disabled: isSaving }), jsx(Label$2, { htmlFor: "policy-notify-assignment", className: "text-sm font-medium text-gray-700 cursor-pointer", children: t('componentsPolicyAssignmentSection.notifyOnAssignment') })] }), jsxs("div", { className: "flex items-center space-x-2", children: [jsx(Checkbox, { id: "policy-notify-removal", checked: notifyOnRemoval, onCheckedChange: (checked) => onNotifyOnRemovalChange(checked === true), disabled: isSaving }), jsx(Label$2, { htmlFor: "policy-notify-removal", className: "text-sm font-medium text-gray-700 cursor-pointer", children: t('componentsPolicyAssignmentSection.notifyOnRemoval') })] })] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", htmlFor: "enabled-policies", children: t('componentsPolicyAssignmentSection.enabledPoliciesLabel') }), jsx(SearchableMultiSelect, { items: policyOptions, selectedItems: selectedPolicies, onSelectionChange: handlePolicySelectionChange, searchQuery: policySearch, onSearchChange: setPolicySearch, isLoading: isPoliciesLoading, placeholder: t('componentsPolicyAssignmentSection.searchPlaceholder'), getItemValue: (policy) => String(policy.id), getItemLabel: (policy) => { var _a; return (((_a = policy.role) === null || _a === void 0 ? void 0 : _a.name) ? `${policy.name}` : policy.name); }, onSelectedItemAction: handleEditPolicyConfig, selectedItemActionIcon: jsx(SquarePen, { className: "h-3 w-3", "aria-hidden": "true" }), selectedItemActionAriaLabel: t('componentsPolicyAssignmentSection.editPolicyAriaLabel'), inputId: "enabled-policies", ariaDescribedBy: "enabled-policies-help", className: "max-w-full" }), jsx("p", { id: "enabled-policies-help", className: "text-xs text-gray-500", children: t('componentsPolicyAssignmentSection.enabledPoliciesHelp') })] })] }), jsx(PolicyConfigDialog, { open: isPolicyConfigDialogOpen, onOpenChange: setIsPolicyConfigDialogOpen, config: activePolicyConfig, onSave: handlePolicyConfigSave })] }));
186096
186132
  }
186097
186133
 
186098
- function useDebouncedValue$1(value, delay) {
186134
+ function useDebouncedValue$2(value, delay) {
186099
186135
  const [debouncedValue, setDebouncedValue] = useState(value);
186100
186136
  useEffect(() => {
186101
186137
  const timer = window.setTimeout(() => setDebouncedValue(value), delay);
@@ -186164,9 +186200,9 @@ function HumanSupportSection({ platformKey, isSaving, recipientMode, onRecipient
186164
186200
  // Track the last initialized data to detect when new data arrives
186165
186201
  const lastInitializedRef = useRef('');
186166
186202
  // Debounced search values
186167
- const debouncedUserSearch = useDebouncedValue$1(userSearch, 300);
186168
- const debouncedGroupSearch = useDebouncedValue$1(groupSearch, 300);
186169
- const debouncedPolicySearch = useDebouncedValue$1(policySearch, 300);
186203
+ const debouncedUserSearch = useDebouncedValue$2(userSearch, 300);
186204
+ const debouncedGroupSearch = useDebouncedValue$2(groupSearch, 300);
186205
+ const debouncedPolicySearch = useDebouncedValue$2(policySearch, 300);
186170
186206
  const shouldFetch = Boolean(platformKey);
186171
186207
  // Fetch users
186172
186208
  const { data: usersResponse, isLoading: isUsersLoading } = usePlatformUsersQuery({
@@ -187804,10 +187840,41 @@ const formatDateToShortFormat$2 = (dateString, isToday = false) => {
187804
187840
  return date.toLocaleDateString([], { month: 'short', day: 'numeric', timeZone: 'UTC' });
187805
187841
  };
187806
187842
 
187843
+ const AnalyticsScopeContext = createContext({ scopedMentor: null });
187844
+ const AnalyticsScopeProvider = AnalyticsScopeContext.Provider;
187845
+ /** Read the analytics agent scope. `scopedMentor` is `null` outside a provider. */
187846
+ function useAnalyticsScope() {
187847
+ return useContext(AnalyticsScopeContext);
187848
+ }
187849
+ /**
187850
+ * The agent a container should report on, in precedence order:
187851
+ *
187852
+ * 1. `selectedMentorId` — an agent the host explicitly switched to.
187853
+ * 2. `mentorId` — the agent in the route, on a per-agent analytics page.
187854
+ * 3. The picker's scope, which only exists on tenant-wide pages.
187855
+ *
187856
+ * The picker comes last so it can never override a host that already knows
187857
+ * which agent the page is about; on those pages `AnalyticsLayout` doesn't
187858
+ * render the picker at all. An empty string is the tenant-wide mode every
187859
+ * analytics hook already understands.
187860
+ */
187861
+ function useScopedMentorId(selectedMentorId, mentorId) {
187862
+ const { scopedMentor } = useAnalyticsScope();
187863
+ return selectedMentorId || mentorId || (scopedMentor === null || scopedMentor === void 0 ? void 0 : scopedMentor.uniqueId) || '';
187864
+ }
187865
+ /**
187866
+ * The database id matching {@link useScopedMentorId}, for the endpoints that
187867
+ * key off the primary key instead of `unique_id`.
187868
+ */
187869
+ function useScopedMentorDbId(selectedMentorDbId) {
187870
+ const { scopedMentor } = useAnalyticsScope();
187871
+ return selectedMentorDbId || (scopedMentor === null || scopedMentor === void 0 ? void 0 : scopedMentor.dbId) || undefined;
187872
+ }
187873
+
187807
187874
  function AnalyticsOverview({ tenantKey, mentorId, selectedMentorId, usergroupIds, }) {
187808
187875
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
187809
187876
  const t = useT();
187810
- const currentMentorId = selectedMentorId || mentorId;
187877
+ const currentMentorId = useScopedMentorId(selectedMentorId, mentorId);
187811
187878
  const { messageStat, topicStat, conversationStat, sessionStats, isLoadingAllStats, isLoadingUsersStats, isLoadingSessionStats, isLoadingTopicsDetailsStats, isLoadingActiveUsersStats, setSessionStatsDateFilter, usersStats, sessionStatsDateFilter, topicsDetailsStats, setTopicsDetailsStatsDateFilter, topicsDetailsStatsDateFilter, activeUsersStats, setUsersStatsDateFilter, usersStatsDateFilter, } = useOverview({ tenantKey, mentorId: currentMentorId, usergroupIds });
187812
187879
  return (jsxs("div", { className: "space-y-8", children: [jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6", children: [jsx(StatCard, { loading: isLoadingAllStats, title: t('analyticsAnalyticsOverview.messages'), value: messageStat.stat, percentage: messageStat.percentage, description: t('analyticsAnalyticsOverview.messagesDescription') }), jsx(StatCard, { loading: isLoadingUsersStats, title: t('analyticsAnalyticsOverview.activeUsers'), value: (usersStats === null || usersStats === void 0 ? void 0 : usersStats.count) || 0, percentage: (usersStats === null || usersStats === void 0 ? void 0 : usersStats.percentage_change) || 0, description: t('analyticsAnalyticsOverview.activeUsersDescription') }), jsx(StatCard, { loading: isLoadingAllStats, title: t('analyticsAnalyticsOverview.topics'), value: topicStat.stat, percentage: topicStat.percentage, description: t('analyticsAnalyticsOverview.topicsDescription') }), jsx(StatCard, { loading: isLoadingAllStats, title: t('analyticsAnalyticsOverview.conversations'), value: conversationStat.stat, percentage: conversationStat.percentage, description: t('analyticsAnalyticsOverview.conversationsDescription') })] }), jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-5", children: [jsx(ChartCardWrapper, { title: t('analyticsAnalyticsOverview.sessions'), label: t('analyticsAnalyticsOverview.sessions'), setOutsideFilters: setSessionStatsDateFilter, filters: sessionStatsDateFilter, description: t('analyticsAnalyticsOverview.sessionsChartDescription'), children: isLoadingSessionStats ? (jsx(ChartLoading, {})) : ((_a = sessionStats === null || sessionStats === void 0 ? void 0 : sessionStats.points) === null || _a === void 0 ? void 0 : _a.length) && ((_b = sessionStats === null || sessionStats === void 0 ? void 0 : sessionStats.points) === null || _b === void 0 ? void 0 : _b.length) > 0 ? (jsxs(LineChart, { data: ((_c = sessionStats === null || sessionStats === void 0 ? void 0 : sessionStats.points) === null || _c === void 0 ? void 0 : _c.map((point) => ({
187813
187880
  date: formatDateToShortFormat$2(point.date, sessionStatsDateFilter.activeFilter === 'today'),
@@ -187844,6 +187911,157 @@ function AnalyticsOverview({ tenantKey, mentorId, selectedMentorId, usergroupIds
187844
187911
  }, cursor: { fill: 'rgba(0, 0, 0, 0.05)' }, wrapperStyle: { outline: 'none' } }), jsx(Bar, { dataKey: "value", fill: "#38A1E5", radius: [4, 4, 0, 0] })] })) : (jsx(EmptyStats, {})) }) })] }));
187845
187912
  }
187846
187913
 
187914
+ /**
187915
+ * Core agent search hook — thin wrapper around `useGetAiSearchMentorsQuery`.
187916
+ *
187917
+ * This is the low-level building block. For a higher-level hook that manages
187918
+ * search state, debounce, and pagination controls, use
187919
+ * `useAgentSearchWithPagination`.
187920
+ */
187921
+ function useAgentSearch({ tenantKey, query, limit = 6, offset, starred, featured, category, subjects, llm, types, includeMainPublicMentors, orderDirection, skip = false, }) {
187922
+ var _a, _b, _c;
187923
+ const { data, isLoading, isFetching, refetch } = useGetAiSearchMentorsQuery({
187924
+ platform_key: tenantKey,
187925
+ query: query || undefined,
187926
+ limit,
187927
+ ...(offset !== undefined && { offset }),
187928
+ ...(starred !== undefined && { starred }),
187929
+ ...(featured !== undefined && { featured }),
187930
+ ...(category && { category }),
187931
+ ...(subjects && { subjects }),
187932
+ ...(llm && { llm }),
187933
+ ...(types && { types }),
187934
+ ...(includeMainPublicMentors !== undefined && {
187935
+ include_main_public_mentors: includeMainPublicMentors,
187936
+ }),
187937
+ ...(orderDirection && { order_direction: orderDirection }),
187938
+ }, { skip: skip || !tenantKey });
187939
+ return {
187940
+ agents: ((_a = data === null || data === void 0 ? void 0 : data.results) !== null && _a !== void 0 ? _a : []),
187941
+ facets: data === null || data === void 0 ? void 0 : data.facets,
187942
+ hasMore: !!(data === null || data === void 0 ? void 0 : data.next),
187943
+ totalCount: (_b = data === null || data === void 0 ? void 0 : data.count) !== null && _b !== void 0 ? _b : 0,
187944
+ totalPages: (_c = data === null || data === void 0 ? void 0 : data.total_pages) !== null && _c !== void 0 ? _c : 0,
187945
+ isLoading,
187946
+ isFetching,
187947
+ refetch,
187948
+ };
187949
+ }
187950
+
187951
+ function c(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(r,n){return r===n}function a(n,t,a){var o=i,f=useRef(n),l=useState({})[1],v=c(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]}
187952
+
187953
+ /**
187954
+ * Higher-level agent search hook that manages search state, debounce, and
187955
+ * pagination controls on top of `useAgentSearch`.
187956
+ *
187957
+ * Use this for simple list/table views (MyMentorsModal, SettingsModal).
187958
+ * For the full explore page with sections, use `useAgentSearch` directly.
187959
+ */
187960
+ function useAgentSearchWithPagination({ itemsPerPage = 6, paginationMode = 'paginated', debounceMs = 500, ...queryConfig }) {
187961
+ const [searchQuery, setSearchQuery] = React__default.useState('');
187962
+ const [debouncedQuery] = a(searchQuery, debounceMs);
187963
+ const [currentPage, setCurrentPage] = React__default.useState(1);
187964
+ const [infiniteLimit, setInfiniteLimit] = React__default.useState(itemsPerPage);
187965
+ // Reset pagination when search changes
187966
+ React__default.useEffect(() => {
187967
+ setCurrentPage(1);
187968
+ setInfiniteLimit(itemsPerPage);
187969
+ }, [debouncedQuery, itemsPerPage]);
187970
+ const isPaginated = paginationMode === 'paginated';
187971
+ const result = useAgentSearch({
187972
+ ...queryConfig,
187973
+ query: debouncedQuery,
187974
+ limit: isPaginated ? itemsPerPage : infiniteLimit,
187975
+ offset: isPaginated ? (currentPage - 1) * itemsPerPage : undefined,
187976
+ });
187977
+ const totalPages = Math.ceil(result.totalCount / itemsPerPage);
187978
+ const handlePageChange = React__default.useCallback((page) => {
187979
+ setCurrentPage(page);
187980
+ }, []);
187981
+ const loadMore = React__default.useCallback(() => {
187982
+ setInfiniteLimit((prev) => prev + itemsPerPage);
187983
+ }, [itemsPerPage]);
187984
+ return {
187985
+ ...result,
187986
+ searchQuery,
187987
+ setSearchQuery,
187988
+ debouncedQuery,
187989
+ currentPage,
187990
+ totalPages,
187991
+ handlePageChange,
187992
+ loadMore,
187993
+ };
187994
+ }
187995
+
187996
+ const AGENTS_PAGE_SIZE = 20;
187997
+ const SEARCH_DEBOUNCE_MS$1 = 300;
187998
+ /** cmdk needs a non-empty value; the handler treats this one as "clear". */
187999
+ const ALL_AGENTS_VALUE = '__all_agents__';
188000
+ function useDebouncedValue$1(value, delay) {
188001
+ const [debounced, setDebounced] = useState(value);
188002
+ useEffect(() => {
188003
+ const timer = setTimeout(() => setDebounced(value), delay);
188004
+ return () => clearTimeout(timer);
188005
+ }, [value, delay]);
188006
+ return debounced;
188007
+ }
188008
+ /**
188009
+ * Scope selector for tenant-wide analytics: either the whole platform, or a
188010
+ * single agent found by typing. Tenant-wide analytics has no agent in the
188011
+ * route, so this is the only way to drill into one without changing pages.
188012
+ *
188013
+ * The list is served by the agent-search endpoint and is not filtered again
188014
+ * client-side — searching is how you reach anything past the first
188015
+ * {@link AGENTS_PAGE_SIZE} results.
188016
+ */
188017
+ function AnalyticsAgentPicker({ tenantKey, value, onChange, className, }) {
188018
+ const t = useT();
188019
+ const [open, setOpen] = useState(false);
188020
+ const [search, setSearch] = useState('');
188021
+ const debouncedSearch = useDebouncedValue$1(search, SEARCH_DEBOUNCE_MS$1);
188022
+ // Skipped until the popover opens, so merely landing on an analytics page
188023
+ // doesn't fire an agent search nobody asked for.
188024
+ const { agents, isFetching } = useAgentSearch({
188025
+ tenantKey,
188026
+ query: debouncedSearch,
188027
+ limit: AGENTS_PAGE_SIZE,
188028
+ skip: !open,
188029
+ });
188030
+ const results = useMemo(
188031
+ // `unique_id` is what the analytics endpoints filter on. A result without
188032
+ // one would produce a selection that silently reports on everything.
188033
+ () => agents.filter((agent) => !!agent.unique_id), [agents]);
188034
+ const handleSelect = (mentor) => {
188035
+ onChange(mentor);
188036
+ setOpen(false);
188037
+ // Re-opening starts from the unfiltered list rather than a stale query.
188038
+ setSearch('');
188039
+ };
188040
+ return (jsxs(Popover, { open: open, onOpenChange: setOpen, children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button$1
188041
+ // Ghost rather than outline: the picker sits in the tab strip's own
188042
+ // background, so it carries no chrome of its own until hovered.
188043
+ , {
188044
+ // Ghost rather than outline: the picker sits in the tab strip's own
188045
+ // background, so it carries no chrome of its own until hovered.
188046
+ variant: "ghost", role: "combobox", "aria-expanded": open, "aria-label": t('analyticsAnalyticsAgentPicker.analyticsScope'), className: cn(
188047
+ // Capped so a long agent name ellipsizes instead of pushing the tab
188048
+ // strip along; the label below is what actually truncates.
188049
+ 'h-9 max-w-[220px] justify-between bg-transparent pl-2 font-normal', className), children: [jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [value ? (jsxs(Avatar, { className: "h-5 w-5 shrink-0", children: [jsx(AvatarImage, { src: value.profileImage, alt: "" }), jsx(AvatarFallback, { className: "text-[10px]", children: value.name.charAt(0).toUpperCase() })] })) : (jsx(Globe, { className: "h-4 w-4 shrink-0 opacity-70", "aria-hidden": "true" })), jsx("span", { className: "min-w-0 truncate", children: value ? value.name : t('analyticsAnalyticsAgentPicker.allAgents') })] }), jsx(ChevronDown, { className: "h-4 w-4 shrink-0 opacity-50", "aria-hidden": "true" })] }) }), jsx(PopoverContent, { "data-iblai-dialog-interaction-layer": true, className: "z-[60] w-[280px] p-0", align: "start", children: jsxs(Command, { shouldFilter: false, children: [jsx(CommandInput, { value: search, onValueChange: setSearch, placeholder: t('analyticsAnalyticsAgentPicker.searchAgents') }), jsxs(CommandList, { children: [jsx(CommandGroup, { children: jsxs(CommandItem, { value: ALL_AGENTS_VALUE, onSelect: () => handleSelect(null), children: [jsx(Check, { className: cn('mr-2 h-4 w-4', value ? 'opacity-0' : 'opacity-100') }), jsx(Globe, { className: "mr-2 h-4 w-4 opacity-70", "aria-hidden": "true" }), t('analyticsAnalyticsAgentPicker.allAgents')] }) }), results.length > 0 && (jsx(CommandGroup, { heading: t('analyticsAnalyticsAgentPicker.agents'), children: results.map((agent) => {
188050
+ var _a;
188051
+ const uniqueId = agent.unique_id;
188052
+ return (jsxs(CommandItem, {
188053
+ // cmdk keys items by value; the search itself is server-side.
188054
+ value: uniqueId, onSelect: () => handleSelect({
188055
+ uniqueId,
188056
+ // Search returns the DB id as a number, but every
188057
+ // consumer downstream types it as a string.
188058
+ dbId: String(agent.id),
188059
+ name: agent.name,
188060
+ profileImage: agent.profile_image,
188061
+ }), children: [jsx(Check, { className: cn('mr-2 h-4 w-4', (value === null || value === void 0 ? void 0 : value.uniqueId) === uniqueId ? 'opacity-100' : 'opacity-0') }), jsxs(Avatar, { className: "mr-2 h-5 w-5 shrink-0", children: [jsx(AvatarImage, { src: agent.profile_image, alt: "" }), jsx(AvatarFallback, { className: "text-[10px]", children: (_a = agent.name) === null || _a === void 0 ? void 0 : _a.charAt(0).toUpperCase() })] }), jsx("span", { className: "truncate", children: agent.name })] }, uniqueId));
188062
+ }) })), isFetching && results.length === 0 && (jsx("div", { className: "px-3 py-4 text-center text-sm text-gray-500", children: t('analyticsAnalyticsAgentPicker.loading') })), !isFetching && results.length === 0 && (jsx("div", { className: "px-3 py-4 text-center text-sm text-gray-500", children: t('analyticsAnalyticsAgentPicker.noAgentsFound') }))] })] }) })] }));
188063
+ }
188064
+
187847
188065
  const defaultTabs = [
187848
188066
  {
187849
188067
  label: 'Overview',
@@ -187887,9 +188105,29 @@ const defaultTabs = [
187887
188105
  },*/
187888
188106
  ];
187889
188107
  const className = 'inline-flex items-center justify-center whitespace-nowrap rounded-[5px] px-2 sm:px-2.5 pt-1 pb-0.5 sm:text-sm text-gray-500 ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:text-blue-600 data-[state=active]:font-semibold text-sm font-medium data-[state=active]:bg-[#f5f7fb] data-[state=active]:shadow-none cursor-pointer';
187890
- function AnalyticsLayout({ children, currentPath, basePath, onTabChange, tabs = defaultTabs, activeTabClassName = '', beforeDataReports, excludeTabs = [], }) {
188108
+ function AnalyticsLayout({ children, currentPath, basePath, onTabChange, tabs = defaultTabs, activeTabClassName = '', beforeDataReports, excludeTabs = [], showPicker = false, tenantKey, scopedMentor, onScopedMentorChange, }) {
188109
+ var _a, _b;
187891
188110
  const { currentTenant } = useCurrentTenant();
187892
188111
  const rbacPermissions = useSelector(selectRbacPermissions);
188112
+ // Deliberately its own state rather than whatever the host already tracks as
188113
+ // "the agent in context": reusing that would silently scope every chart to
188114
+ // the last agent the user chatted with, with nothing on screen saying why.
188115
+ // The trade-off is that it resets on reload — a host that needs it shareable
188116
+ // controls the value instead.
188117
+ const [internalScopedMentor, setInternalScopedMentor] = useState(null);
188118
+ const isScopeControlled = onScopedMentorChange !== undefined;
188119
+ const activeScopedMentor = (_a = (isScopeControlled ? scopedMentor : internalScopedMentor)) !== null && _a !== void 0 ? _a : null;
188120
+ const handleScopedMentorChange = useCallback((mentor) => {
188121
+ if (isScopeControlled) {
188122
+ onScopedMentorChange === null || onScopedMentorChange === void 0 ? void 0 : onScopedMentorChange(mentor);
188123
+ return;
188124
+ }
188125
+ setInternalScopedMentor(mentor);
188126
+ }, [isScopeControlled, onScopedMentorChange]);
188127
+ const scopeValue = useMemo(
188128
+ // Only a rendered picker may scope the page — otherwise a host that stops
188129
+ // showing it would leave a stale agent filtering every chart.
188130
+ () => ({ scopedMentor: showPicker ? activeScopedMentor : null }), [showPicker, activeScopedMentor]);
187893
188131
  // Only a pure watcher narrows the tab strip — everyone else keeps whatever
187894
188132
  // the caller passed, custom tabs included.
187895
188133
  const isRestricted = isPureWatcher(rbacPermissions, currentTenant);
@@ -187959,12 +188197,12 @@ function AnalyticsLayout({ children, currentPath, basePath, onTabChange, tabs =
187959
188197
  return;
187960
188198
  onTabChange(tabValue);
187961
188199
  };
187962
- return (jsxs("div", { className: "flex flex-col flex-1 min-h-0 h-full overflow-hidden overscroll-none bg-[#f5f7fb]", children: [jsx("div", { className: "p-6 pb-0 pt-4 xs:pt-0", children: jsx("div", { className: "flex items-center justify-between mb-4 xs:mb-2", children: jsxs("div", { className: "flex items-center justify-between w-full overflow-x-auto", children: [jsx(Tabs, { className: "bg-[#f5f7fb]", value: activeTab, children: jsx(TabsList, { className: "bg-[#f5f7fb]", children: tabs
187963
- .filter((tab) => !excludeTabs.includes(tab.value) && canAccessTab(tab.value))
187964
- .map((tab) => {
187965
- const isActive = activeTab === tab.value;
187966
- return (jsx(TabsTrigger, { value: tab.value, className: cn(className, isActive && activeTabClassName), onClick: () => handleTabClick(tab.value), children: tab.label }, tab.value));
187967
- }) }) }), jsxs("div", { className: "flex items-center gap-4", children: [beforeDataReports, canAccessTab('reports') && (jsx(Tabs, { className: "bg-[#f5f7fb]", value: activeTab, children: jsx(TabsList, { className: "bg-[#f5f7fb]", children: jsx(TabsTrigger, { value: "reports", className: cn(className, activeTab === 'reports' && activeTabClassName), onClick: () => handleTabClick('reports'), children: "Data Reports" }) }) }))] })] }) }) }), jsx("div", { className: "flex-1 overflow-auto overscroll-contain scrollbar-none px-6 pb-6 pt-0", children: isActiveTabAllowed ? children : null })] }));
188200
+ return (jsx(AnalyticsScopeProvider, { value: scopeValue, children: jsxs("div", { className: "flex flex-col flex-1 min-h-0 h-full overflow-hidden overscroll-none bg-[#f5f7fb]", children: [jsx("div", { className: "p-6 pb-0 pt-4 xs:pt-0", children: jsx("div", { className: "flex items-center justify-between mb-4 xs:mb-2", children: jsxs("div", { className: "flex items-center justify-between w-full overflow-x-auto", children: [jsxs("div", { className: "flex items-center gap-3", children: [showPicker && (jsx("div", { className: "shrink-0", children: jsx(AnalyticsAgentPicker, { tenantKey: (_b = tenantKey !== null && tenantKey !== void 0 ? tenantKey : currentTenant === null || currentTenant === void 0 ? void 0 : currentTenant.key) !== null && _b !== void 0 ? _b : '', value: activeScopedMentor, onChange: handleScopedMentorChange }) })), jsx(Tabs, { className: "bg-[#f5f7fb]", value: activeTab, children: jsx(TabsList, { className: "bg-[#f5f7fb]", children: tabs
188201
+ .filter((tab) => !excludeTabs.includes(tab.value) && canAccessTab(tab.value))
188202
+ .map((tab) => {
188203
+ const isActive = activeTab === tab.value;
188204
+ return (jsx(TabsTrigger, { value: tab.value, className: cn(className, isActive && activeTabClassName), onClick: () => handleTabClick(tab.value), children: tab.label }, tab.value));
188205
+ }) }) })] }), jsxs("div", { className: "flex items-center gap-4", children: [beforeDataReports, canAccessTab('reports') && (jsx(Tabs, { className: "bg-[#f5f7fb]", value: activeTab, children: jsx(TabsList, { className: "bg-[#f5f7fb]", children: jsx(TabsTrigger, { value: "reports", className: cn(className, activeTab === 'reports' && activeTabClassName), onClick: () => handleTabClick('reports'), children: "Data Reports" }) }) }))] })] }) }) }), jsx("div", { className: "flex-1 overflow-auto overscroll-contain scrollbar-none px-6 pb-6 pt-0", children: isActiveTabAllowed ? children : null })] }) }));
187968
188206
  }
187969
188207
 
187970
188208
  const accessTimeData = [
@@ -188186,7 +188424,7 @@ const formatRelativeTime$1 = (dateString, t) => {
188186
188424
  function AnalyticsUsersStats({ tenantKey, mentorId, selectedMentorId, usergroupIds, }) {
188187
188425
  var _a, _b, _c, _d, _e, _f, _g, _h;
188188
188426
  const t = useT();
188189
- const currentMentorId = selectedMentorId || mentorId;
188427
+ const currentMentorId = useScopedMentorId(selectedMentorId, mentorId);
188190
188428
  const { registeredUsers, isLoadingRegisteredUsers, activeUsers, isLoadingActiveUsers, setActiveUsersStatsDateFilter, activeUsersStatsDateFilter, accessTimeHeatmap, isLoadingAccessTimeHeatmap, setAccessTimeHeatmapDateFilter, accessTimeHeatmapDateFilter, userDetailsStats, isLoadingUserDetailsStats, setUserDetailsStatsDateFilter, userDetailsStatsDateFilter, setUserDetailsStatsPage, userDetailsStatsSearch, handleSearchInputChange, currentlyActiveUsers, isLoadingCurrentlyActiveUsers, activeUsers30D, isLoadingActiveUsers30D, } = useUsers({ tenantKey, mentorId: currentMentorId, usergroupIds });
188191
188429
  return (jsxs("div", { className: "space-y-8", children: [jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 mb-6", children: [jsx(StatCard, { title: t('analyticsAnalyticsUsersStats.usersLoggedInNow'), value: (currentlyActiveUsers === null || currentlyActiveUsers === void 0 ? void 0 : currentlyActiveUsers.count) || 0, loading: isLoadingCurrentlyActiveUsers, description: t('analyticsAnalyticsUsersStats.usersLoggedInNowDescription') }), jsx(StatCard, { title: t('analyticsAnalyticsUsersStats.usersLoggedInPast30Days'), value: (activeUsers30D === null || activeUsers30D === void 0 ? void 0 : activeUsers30D.count) || 0, loading: isLoadingActiveUsers30D, description: t('analyticsAnalyticsUsersStats.usersLoggedInPast30DaysDescription') }), jsx(StatCard, { title: t('analyticsAnalyticsUsersStats.totalRegisteredUsers'), value: (registeredUsers === null || registeredUsers === void 0 ? void 0 : registeredUsers.count) || 0, loading: isLoadingRegisteredUsers, description: t('analyticsAnalyticsUsersStats.totalRegisteredUsersDescription') })] }), jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-5", children: [jsx(ChartCardWrapper, { title: t('analyticsAnalyticsUsersStats.activeUsersTitle'), label: t('analyticsAnalyticsUsersStats.activeUsersLabel'), filters: activeUsersStatsDateFilter, setOutsideFilters: setActiveUsersStatsDateFilter, description: t('analyticsAnalyticsUsersStats.activeUsersChartDescription'), children: isLoadingActiveUsers ? (jsx(ChartLoading, {})) : ((_a = activeUsers === null || activeUsers === void 0 ? void 0 : activeUsers.points) === null || _a === void 0 ? void 0 : _a.length) && ((_b = activeUsers === null || activeUsers === void 0 ? void 0 : activeUsers.points) === null || _b === void 0 ? void 0 : _b.length) > 0 ? (jsxs(BarChart, { data: (_c = activeUsers === null || activeUsers === void 0 ? void 0 : activeUsers.points) === null || _c === void 0 ? void 0 : _c.map((point) => ({
188192
188430
  date: formatDateToShortFormat$2(point.date, activeUsersStatsDateFilter.activeFilter === 'today'),
@@ -188292,7 +188530,7 @@ const useTopics = ({ tenantKey, mentorId, usergroupIds, }) => {
188292
188530
  function AnalyticsTopicsStats({ tenantKey, mentorId, selectedMentorId, usergroupIds, }) {
188293
188531
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
188294
188532
  const t = useT();
188295
- const currentMentorId = selectedMentorId || mentorId;
188533
+ const currentMentorId = useScopedMentorId(selectedMentorId, mentorId);
188296
188534
  const { topicsStats, isLoadingTopicsStats, conversationsStats, isLoadingConversationsStats, conversationsStatsDateFilter, setConversationsStatsDateFilter, averageRatingStats, averageRatingDateFilter, setAverageRatingDateFilter, topicsDetailsStats, isLoadingTopicsDetailsStats, topicsDetailsDateFilter, setTopicsDetailsDateFilter, } = useTopics({ tenantKey, mentorId: currentMentorId, usergroupIds });
188297
188535
  const averageRatingDisplayed = ((_a = averageRatingStats === null || averageRatingStats === void 0 ? void 0 : averageRatingStats.points) === null || _a === void 0 ? void 0 : _a.length) && ((_b = averageRatingStats === null || averageRatingStats === void 0 ? void 0 : averageRatingStats.points) === null || _b === void 0 ? void 0 : _b.length) > 0;
188298
188536
  return (jsxs("div", { className: "space-y-8", children: [jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 mb-6", children: [jsx(StatCard, { title: t('analyticsAnalyticsTopicsStats.topics'), value: ((_c = topicsStats === null || topicsStats === void 0 ? void 0 : topicsStats.topics) === null || _c === void 0 ? void 0 : _c.this_month) || 0, loading: isLoadingTopicsStats, percentage: ((_d = topicsStats === null || topicsStats === void 0 ? void 0 : topicsStats.topics) === null || _d === void 0 ? void 0 : _d.percentage_change) || 0, description: t('analyticsAnalyticsTopicsStats.topicsDescription') }), jsx(StatCard, { title: t('analyticsAnalyticsTopicsStats.conversations'), value: ((_e = topicsStats === null || topicsStats === void 0 ? void 0 : topicsStats.conversations) === null || _e === void 0 ? void 0 : _e.this_month) || 0, loading: isLoadingTopicsStats, percentage: ((_f = topicsStats === null || topicsStats === void 0 ? void 0 : topicsStats.conversations) === null || _f === void 0 ? void 0 : _f.percentage_change) || 0, description: t('analyticsAnalyticsTopicsStats.conversationsDescription') }), jsx(StatCard, { title: t('analyticsAnalyticsTopicsStats.messages'), value: ((_g = topicsStats === null || topicsStats === void 0 ? void 0 : topicsStats.messages) === null || _g === void 0 ? void 0 : _g.this_month) || 0, loading: isLoadingTopicsStats, percentage: ((_h = topicsStats === null || topicsStats === void 0 ? void 0 : topicsStats.messages) === null || _h === void 0 ? void 0 : _h.percentage_change) || 0, description: t('analyticsAnalyticsTopicsStats.messagesDescription') })] }), jsxs("div", { className: cn('grid grid-cols-1 lg:grid-cols-2 gap-5', !averageRatingDisplayed ? 'lg:grid-cols-1' : ''), children: [jsx(ChartCardWrapper, { title: t('analyticsAnalyticsTopicsStats.conversations'), label: t('analyticsAnalyticsTopicsStats.conversations'), filters: conversationsStatsDateFilter, setOutsideFilters: setConversationsStatsDateFilter, description: t('analyticsAnalyticsTopicsStats.conversationsChartDescription'), children: isLoadingConversationsStats ? (jsx(ChartLoading, {})) : ((_j = conversationsStats === null || conversationsStats === void 0 ? void 0 : conversationsStats.points) === null || _j === void 0 ? void 0 : _j.length) && ((_k = conversationsStats === null || conversationsStats === void 0 ? void 0 : conversationsStats.points) === null || _k === void 0 ? void 0 : _k.length) > 0 ? (jsxs(LineChart, { data: (_l = conversationsStats === null || conversationsStats === void 0 ? void 0 : conversationsStats.points) === null || _l === void 0 ? void 0 : _l.map((point) => ({
@@ -188508,7 +188746,7 @@ const useFinancial = ({ tenantKey, mentorId, usergroupIds, }) => {
188508
188746
  function AnalyticsFinancialStats({ tenantKey, mentorId, selectedMentorId, usergroupIds, }) {
188509
188747
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
188510
188748
  const t = useT();
188511
- const currentMentorId = selectedMentorId || mentorId;
188749
+ const currentMentorId = useScopedMentorId(selectedMentorId, mentorId);
188512
188750
  const { weeklyCostData, isLoadingWeeklyCostData, monthlyCostData, isLoadingMonthlyCostData, totalCostData, isLoadingTotalCostData, detailedCostPerDayData, isLoadingDetailedCostPerDayData, detailedCostPerDayFilters, setDetailedCostPerDayFilters, detailedCostPerProviderData, isLoadingDetailedCostPerProviderData, detailedCostPerProviderFilters, setDetailedCostPerProviderFilters, detailedCostPerUserData, isLoadingDetailedCostPerUserData, detailedCostPerUserFilters, setDetailedCostPerUserFilters, costPerUserPage, setCostPerUserPage, costPerUserLimit, providerColors, detailedLLMCostData, isLoadingDetailedLLMCostData, detailedLLMCostFilters, setDetailedLLMCostFilters, } = useFinancial({ tenantKey, mentorId: currentMentorId, usergroupIds });
188513
188751
  // Pagination handlers
188514
188752
  const handleFirstPage = () => {
@@ -223207,7 +223445,7 @@ const getMessageContent = (content) => {
223207
223445
  function AnalyticsTranscriptsStats({ tenantKey, mentorId, selectedMentorId, usergroupIds, }) {
223208
223446
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
223209
223447
  const t = useT();
223210
- const currentMentorId = selectedMentorId || mentorId;
223448
+ const currentMentorId = useScopedMentorId(selectedMentorId, mentorId);
223211
223449
  const [isModalOpen, setIsModalOpen] = useState(false);
223212
223450
  const searchParams = useSearchParams();
223213
223451
  const router = useRouter();
@@ -223820,6 +224058,8 @@ function AnalyticsReports({ tenantKey, selectedMentorId, disabledReports = [], u
223820
224058
  const t = useT();
223821
224059
  const { currentTenant } = useCurrentTenant();
223822
224060
  const rbacPermissions = useSelector(selectRbacPermissions);
224061
+ const scopedMentorId = useScopedMentorId(selectedMentorId);
224062
+ const scopedMentorDbId = useScopedMentorDbId(selectedMentorDbId);
223823
224063
  const { metadata } = useTenantMetadata({ org: tenantKey });
223824
224064
  //we using metadata to get the combined recommendation reports
223825
224065
  //"combined_recommendation_reports": "Recommendation History Report,Course Grade Report,User Group Member List Report",
@@ -223831,9 +224071,11 @@ function AnalyticsReports({ tenantKey, selectedMentorId, disabledReports = [], u
223831
224071
  }, [metadata === null || metadata === void 0 ? void 0 : metadata.combined_recommendation_reports, metadata === null || metadata === void 0 ? void 0 : metadata.enable_combined_recommendation_report]);
223832
224072
  const { reports, isLoading, initializeReportDownload, activeReportName, isGenerating } = useReports({
223833
224073
  tenantKey,
223834
- selectedMentorId,
224074
+ // Reports keys off both ids: `unique_id` for the agent's public settings,
224075
+ // and the database id for the `mentor_id` filter on the report list.
224076
+ selectedMentorId: scopedMentorId,
223835
224077
  usergroupIds,
223836
- selectedMentorDbId,
224078
+ selectedMentorDbId: scopedMentorDbId,
223837
224079
  });
223838
224080
  const [fetchReportBlob] = useLazyGetDownloadReportFromURLQuery();
223839
224081
  const fetchAuthenticatedContent = useCallback(async (url) => {
@@ -224579,7 +224821,7 @@ function AnalyticsCourses({ tenantKey, mentorId, selectedMentorId, basePath = ''
224579
224821
  var _a, _b, _c, _d;
224580
224822
  const t = useT();
224581
224823
  const router = useRouter();
224582
- const currentMentorId = selectedMentorId || mentorId;
224824
+ const currentMentorId = useScopedMentorId(selectedMentorId, mentorId);
224583
224825
  const { courseStats, isLoading, enrollmentStats, enrollmentStatsDateFilter, setEnrollmentStatsDateFilter, coursesList, setCoursesListPage, coursesListSearch, handleSearchInputChange, coursesPagination, } = useCourses({ tenantKey, mentorId: currentMentorId });
224584
224826
  const handleCourseClick = (courseId) => {
224585
224827
  router.push(`${basePath}/courses/${courseId}`);
@@ -224631,7 +224873,7 @@ function AnalyticsCourses({ tenantKey, mentorId, selectedMentorId, basePath = ''
224631
224873
  function AnalyticsCourseDetail({ tenantKey, mentorId, selectedMentorId, courseId, courseName, showCourseTitle = true, onBack, }) {
224632
224874
  var _a, _b;
224633
224875
  const t = useT();
224634
- const currentMentorId = selectedMentorId || mentorId;
224876
+ const currentMentorId = useScopedMentorId(selectedMentorId, mentorId);
224635
224877
  const { courseDetailStats, isLoading, courseEnrollments, courseEnrollmentsSearch, handleCourseEnrollmentsSearchInputChange, setCourseEnrollmentsPage, courseEnrollmentsPagination, courseInfo, } = useCourses({
224636
224878
  tenantKey,
224637
224879
  mentorId: currentMentorId,
@@ -224938,7 +225180,7 @@ function AnalyticsPrograms({ tenantKey, mentorId, selectedMentorId, basePath = '
224938
225180
  var _a, _b, _c, _d;
224939
225181
  const t = useT();
224940
225182
  const router = useRouter();
224941
- const currentMentorId = selectedMentorId || mentorId;
225183
+ const currentMentorId = useScopedMentorId(selectedMentorId, mentorId);
224942
225184
  const { programStats, isLoading, enrollmentStats, enrollmentStatsDateFilter, setEnrollmentStatsDateFilter, programsList, setProgramsListPage, programsListSearch, handleSearchInputChange, programsPagination, } = usePrograms({ tenantKey, mentorId: currentMentorId });
224943
225185
  const handleProgramClick = (programId) => {
224944
225186
  router.push(`${basePath}/programs/${programId}`);
@@ -224990,7 +225232,7 @@ function AnalyticsPrograms({ tenantKey, mentorId, selectedMentorId, basePath = '
224990
225232
  function AnalyticsProgramDetail({ tenantKey, mentorId, selectedMentorId, programId, programName, onBack, }) {
224991
225233
  var _a, _b;
224992
225234
  const t = useT();
224993
- const currentMentorId = selectedMentorId || mentorId;
225235
+ const currentMentorId = useScopedMentorId(selectedMentorId, mentorId);
224994
225236
  const { programDetailStats, isLoading, programEnrollments, programEnrollmentsSearch, handleProgramEnrollmentsSearchInputChange, setProgramEnrollmentsPage, programEnrollmentsPagination, programInfo, } = usePrograms({
224995
225237
  tenantKey,
224996
225238
  mentorId: currentMentorId,
@@ -225930,7 +226172,7 @@ function summarizeChanges(entry) {
225930
226172
  function AgentAuditLogView({ tenantKey, mentorId, userId, selectedMentorId, }) {
225931
226173
  var _a;
225932
226174
  const t = useT();
225933
- const currentMentorId = selectedMentorId || mentorId;
226175
+ const currentMentorId = useScopedMentorId(selectedMentorId, mentorId);
225934
226176
  const [actorOpen, setActorOpen] = useState(false);
225935
226177
  const { data, isLoading, error, page, setPage, totalPages, actionFilter, setActionFilter, actorFilter, setActorFilter, dateRange, setDateRange, } = useAuditLog({
225936
226178
  tenantKey,
@@ -225984,88 +226226,6 @@ function AnalyticsAuditLogStats({ tenantKey, mentorId, userId, selectedMentorId,
225984
226226
  : t('analyticsAnalyticsAuditLogStats.scopePlatformHint') })] })), activeScope === 'platform' ? (jsx(AnalyticsPlatformAuditLog, { platformKey: tenantKey, timezone: timezone })) : (jsx(AgentAuditLogView, { tenantKey: tenantKey, mentorId: mentorId, userId: userId, selectedMentorId: selectedMentorId }))] }));
225985
226227
  }
225986
226228
 
225987
- /**
225988
- * Core agent search hook — thin wrapper around `useGetAiSearchMentorsQuery`.
225989
- *
225990
- * This is the low-level building block. For a higher-level hook that manages
225991
- * search state, debounce, and pagination controls, use
225992
- * `useAgentSearchWithPagination`.
225993
- */
225994
- function useAgentSearch({ tenantKey, query, limit = 6, offset, starred, featured, category, subjects, llm, types, includeMainPublicMentors, orderDirection, skip = false, }) {
225995
- var _a, _b, _c;
225996
- const { data, isLoading, isFetching, refetch } = useGetAiSearchMentorsQuery({
225997
- platform_key: tenantKey,
225998
- query: query || undefined,
225999
- limit,
226000
- ...(offset !== undefined && { offset }),
226001
- ...(starred !== undefined && { starred }),
226002
- ...(featured !== undefined && { featured }),
226003
- ...(category && { category }),
226004
- ...(subjects && { subjects }),
226005
- ...(llm && { llm }),
226006
- ...(types && { types }),
226007
- ...(includeMainPublicMentors !== undefined && {
226008
- include_main_public_mentors: includeMainPublicMentors,
226009
- }),
226010
- ...(orderDirection && { order_direction: orderDirection }),
226011
- }, { skip: skip || !tenantKey });
226012
- return {
226013
- agents: ((_a = data === null || data === void 0 ? void 0 : data.results) !== null && _a !== void 0 ? _a : []),
226014
- facets: data === null || data === void 0 ? void 0 : data.facets,
226015
- hasMore: !!(data === null || data === void 0 ? void 0 : data.next),
226016
- totalCount: (_b = data === null || data === void 0 ? void 0 : data.count) !== null && _b !== void 0 ? _b : 0,
226017
- totalPages: (_c = data === null || data === void 0 ? void 0 : data.total_pages) !== null && _c !== void 0 ? _c : 0,
226018
- isLoading,
226019
- isFetching,
226020
- refetch,
226021
- };
226022
- }
226023
-
226024
- function c(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(r,n){return r===n}function a(n,t,a){var o=i,f=useRef(n),l=useState({})[1],v=c(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]}
226025
-
226026
- /**
226027
- * Higher-level agent search hook that manages search state, debounce, and
226028
- * pagination controls on top of `useAgentSearch`.
226029
- *
226030
- * Use this for simple list/table views (MyMentorsModal, SettingsModal).
226031
- * For the full explore page with sections, use `useAgentSearch` directly.
226032
- */
226033
- function useAgentSearchWithPagination({ itemsPerPage = 6, paginationMode = 'paginated', debounceMs = 500, ...queryConfig }) {
226034
- const [searchQuery, setSearchQuery] = React__default.useState('');
226035
- const [debouncedQuery] = a(searchQuery, debounceMs);
226036
- const [currentPage, setCurrentPage] = React__default.useState(1);
226037
- const [infiniteLimit, setInfiniteLimit] = React__default.useState(itemsPerPage);
226038
- // Reset pagination when search changes
226039
- React__default.useEffect(() => {
226040
- setCurrentPage(1);
226041
- setInfiniteLimit(itemsPerPage);
226042
- }, [debouncedQuery, itemsPerPage]);
226043
- const isPaginated = paginationMode === 'paginated';
226044
- const result = useAgentSearch({
226045
- ...queryConfig,
226046
- query: debouncedQuery,
226047
- limit: isPaginated ? itemsPerPage : infiniteLimit,
226048
- offset: isPaginated ? (currentPage - 1) * itemsPerPage : undefined,
226049
- });
226050
- const totalPages = Math.ceil(result.totalCount / itemsPerPage);
226051
- const handlePageChange = React__default.useCallback((page) => {
226052
- setCurrentPage(page);
226053
- }, []);
226054
- const loadMore = React__default.useCallback(() => {
226055
- setInfiniteLimit((prev) => prev + itemsPerPage);
226056
- }, [itemsPerPage]);
226057
- return {
226058
- ...result,
226059
- searchQuery,
226060
- setSearchQuery,
226061
- debouncedQuery,
226062
- currentPage,
226063
- totalPages,
226064
- handlePageChange,
226065
- loadMore,
226066
- };
226067
- }
226068
-
226069
226229
  function MentorSelectionGrid({ selectedMentorIds, onMentorSelect, searchQuery, onSearchChange, tenantKey, itemsPerPage = 8, showSearch = true, minHeight = '400px', }) {
226070
226230
  const t = useT();
226071
226231
  const { agents: mentors, isLoading: isMentorsLoading, isFetching: isMentorsFetching, currentPage, totalPages, setSearchQuery: setMentorSearch, handlePageChange, } = useAgentSearchWithPagination({ tenantKey, itemsPerPage });
@@ -226464,6 +226624,7 @@ function AgentSearchDialog({ tenantKey, open, onClose, selectedMentorId, onSelec
226464
226624
  */
226465
226625
  function AnalyticsMemoryStats({ tenantKey, mentorId, userId, selectedMentorId, myMemory = false, }) {
226466
226626
  const t = useT();
226627
+ const scopedMentorId = useScopedMentorId(selectedMentorId, mentorId);
226467
226628
  const [selectedMemory, setSelectedMemory] = useState(null);
226468
226629
  const [agentSearchOpen, setAgentSearchOpen] = useState(false);
226469
226630
  // The content search is committed on Enter/blur rather than per-keystroke so
@@ -226472,7 +226633,10 @@ function AnalyticsMemoryStats({ tenantKey, mentorId, userId, selectedMentorId, m
226472
226633
  const { scope, setScope, availableScopes, searchedMentor, selectSearchedMentor, rows, aggregates, categories, isLoading, error, isForbidden, page, setPage, totalPages, learnerFilter, setLearnerFilter, categoryFilter, setCategoryFilter, setContentFilter, dateRange, setDateRange, } = useMemory({
226473
226634
  tenantKey,
226474
226635
  userId,
226475
- mentorId: selectedMentorId || mentorId,
226636
+ // The agent scope picker feeds the same slot the route agent would, so the
226637
+ // tab's own agent search still overrides it (`searchedMentor || mentorId`)
226638
+ // rather than the two controls fighting over the scope.
226639
+ mentorId: scopedMentorId,
226476
226640
  myMemory,
226477
226641
  });
226478
226642
  const scopeLabels = {
@@ -237305,5 +237469,5 @@ var trainOrDeleteModal = /*#__PURE__*/Object.freeze({
237305
237469
  TrainOrDeleteModal: TrainOrDeleteModal
237306
237470
  });
237307
237471
 
237308
- export { ACCESS_COURSE_LABEL, ALL_CATEGORIES, AccessTimeHeatmap, AccessiblePaginate, AddMentorToProjectModal, AddSkillDialog, Admin, AdvancedTab, AgentConfigPrompts, AgentSkills, AlertsTab, AnalyticsAuditLogStats, AnalyticsCourseDetail, AnalyticsCourses, AnalyticsFinancialStats, AnalyticsLayout, AnalyticsMemoryStats, AnalyticsMonetizationStats, AnalyticsOverview, AnalyticsPlatformAuditLog, AnalyticsProgramDetail, AnalyticsPrograms, AnalyticsReportDownload, AnalyticsReports, AnalyticsSettingsProvider, AnalyticsTopicsStats, AnalyticsTranscriptsStats, AnalyticsUsersStats, AppleRestrictionModal, ApplyWizard, AuditLogChangesView, AuditLogJsonView, BUY_NOW_LABEL, BillingTab, CATALOGS, CREATE_AGENT_LABELS, CUA_DRIVER_REPO_URL, CUA_DRIVER_TAURI_COMMANDS, CUA_DRIVER_TAURI_EVENTS, CardInfoIcon, CategorizedDropdownMenu, ChartCardWrapper, ChartFiltersProvider, ChartLoading, ChatContext, ChatPrivacyToggle, ChatProvider, CompanyDialog, ConnectorManagementDialog, CopyButtonIcon, CourseAccessGuard, CourseCardSkeleton, CourseContentLoading, CourseOutline, CourseOutlineContext, CourseOutlineDrawer, CreateAgentForm, CreateAgentModal, CreateProjectModal, CreateWorkflowModal, CredentialBox, CredentialMiniBoxSkeleton, CredentialsList, CreditBalance, CustomDateRangePicker, CustomTooltip, DEFAULT_COWORK_REQUIRED_SIZE_GB, DEFAULT_LOCALE, DefaultEmptyBox, DeleteProjectModal, DeleteWorkflowModal, DiscoverContentCard, DiscoverFacetsFilter, DiscoverFilterDrawer, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, ENROLL_NOW_COURSE_STARTING_SOON_LABEL, ENROLL_NOW_LABEL, EditAlertDialog, EducationBox, EducationDialog, EducationTab, EdxIframeContext, EmptyStats, ExperienceBox, ExperienceDialog, ExperienceTab, FacetFilterContext, Footer, GradebookTab, GroupsFilterDropdown, INVITATION_ONLY_LABEL, InstitutionDialog, IntegrationsTab, InviteUserContent, InviteUserDialog, InvitedUsersDialog, LOCAL_MODELS, Loader, LocalLLMTab, LocalModelsContent, LoginButton, MACOS_PERMISSIONS_COMMANDS, MEMORY_PAGE_SIZE, Markdown, MinimumMentorAlert, MonetizationTab, NotificationDisplay, NotificationDropdown, ONBOARDING_SECTORS, OnboardingShell, OnboardingWizard, PLATFORM_AUDIT_DEEP_PAGING_THRESHOLD, PLATFORM_AUDIT_PAGE_SIZE, PaywallModal, PlacementExam, PlacementExamsDropdown, PlatformAuditLogDetailSheet, PlatformNavbar, PlatformNavbarSearch, Profile, ProfileTimeChart, ProgressDots, ProjectActionButtons, ProjectFilesModal, ProjectInstructionsModal, ProjectLandingPage, ProjectMentorsList, ProjectsPage, REQUEST_ACCESS_COURSE_STARTING_SOON_LABEL, REQUEST_ACCESS_LABEL, RenameProjectModal, ResumeBox, ResumeTab, RichTextEditor, SUPPORTED_LOCALES, SandboxConfig, SearchableMultiSelect, SendNotificationDialog, SignupButton, SkeletonActivityStatBox, SkeletonAddSkillsLoading, SkeletonCreatePathwaySearchList, SkeletonDiscoverFilterBox, SkeletonEducationBox, SkeletonMultiplier, SkeletonPathwayBox, SkeletonProfileInfoCard, SkeletonSkillBox, SkillBox, SkillDetailModal, SkillLeaderboardChart, SkillsBox, SkillsList, SlashSkillPicker, Spinner, StatCard, StepHeader, TAURI_COMMANDS, TAURI_EVENTS, TenantSwitcher, TimeFilter, TimeTrackingProvider, TimedExam, ToolDialogs, TopBanner, UpgradePackageModal, UserAvatar, Version, WebContainersI18nProvider, WorkflowSidebar, addBookmarksTab, availablePlacementExams, findLastResumeBlock, findSequentialParent, flattenVerticalBlocks, formatAuditTimestamp, formatTimeZoneLabel, getCatalog, getFirstAvailableUnit, getLocalLLMModel, getLocalLLMToolSupport, getNextUnitIframe, getOrg, getParentBlockById, getParentsInfosFromSublessonId, getPreviousUnitIframe, getRandomCourseImage, getSectorById, getTenant, getUnitToIframe, getUserId, getUserName, humanizeAuditToken, inBrowserPrint, inIframe, initialCuaDriverInstallState, initialModelDownloadState, isCoworkEnabled, isLocalLLMEnabled, isPlatformNavbarCreditBalanceVisible, isSlashCommandToken, isTauriApp, isValidLocale, isValidTimeZone, components as markdownComponents, modelSupportsCowork, onboardingPrimaryButtonClass, onboardingSecondaryButtonClass, resolveAuditTimeZone, resolveCreateAgentLabels, sanitizeCss, setCoworkEnabled, setLocalLLMEnabled, setLocalLLMModel, setLocalLLMToolSupport, smallestCoworkModel, useAnalyticsSettings, useAuditLog, useCatalogSearch, useChartFilters, useChatPrivacy, useChatState, useCourseDetail, useCourseMetadata, useCourses, useCuaDriver, useDiscover, useEdxIframe, useFinancial, useIframeMessageHandler, useLocalStorage, useMemory, useModelDownload, useMonetization, useOverview, usePlatformAuditLabels, usePlatformAuditLog, useProfileActivityStats, useProfileCredentials, useProfilePathways, useProfilePrograms, useProfileSkills, useProfileTimeSpent, usePrograms, useReports, useSlashSkillPicker, useSlashSkills, useT, useTauri, useTimeTracking, useTopics, useTranscripts, useUserCourses, useUserMetadata, useUsers, useWebContainersI18n, useWebContainersLocale };
237472
+ export { ACCESS_COURSE_LABEL, ALL_CATEGORIES, AccessTimeHeatmap, AccessiblePaginate, AddMentorToProjectModal, AddSkillDialog, Admin, AdvancedTab, AgentConfigPrompts, AgentSkills, AlertsTab, AnalyticsAgentPicker, AnalyticsAuditLogStats, AnalyticsCourseDetail, AnalyticsCourses, AnalyticsFinancialStats, AnalyticsLayout, AnalyticsMemoryStats, AnalyticsMonetizationStats, AnalyticsOverview, AnalyticsPlatformAuditLog, AnalyticsProgramDetail, AnalyticsPrograms, AnalyticsReportDownload, AnalyticsReports, AnalyticsScopeProvider, AnalyticsSettingsProvider, AnalyticsTopicsStats, AnalyticsTranscriptsStats, AnalyticsUsersStats, AppleRestrictionModal, ApplyWizard, AuditLogChangesView, AuditLogJsonView, BUY_NOW_LABEL, BillingTab, CATALOGS, CREATE_AGENT_LABELS, CUA_DRIVER_REPO_URL, CUA_DRIVER_TAURI_COMMANDS, CUA_DRIVER_TAURI_EVENTS, CardInfoIcon, CategorizedDropdownMenu, ChartCardWrapper, ChartFiltersProvider, ChartLoading, ChatContext, ChatPrivacyToggle, ChatProvider, CompanyDialog, ConnectorManagementDialog, CopyButtonIcon, CourseAccessGuard, CourseCardSkeleton, CourseContentLoading, CourseOutline, CourseOutlineContext, CourseOutlineDrawer, CreateAgentForm, CreateAgentModal, CreateProjectModal, CreateWorkflowModal, CredentialBox, CredentialMiniBoxSkeleton, CredentialsList, CreditBalance, CustomDateRangePicker, CustomTooltip, DEFAULT_COWORK_REQUIRED_SIZE_GB, DEFAULT_LOCALE, DefaultEmptyBox, DeleteProjectModal, DeleteWorkflowModal, DiscoverContentCard, DiscoverFacetsFilter, DiscoverFilterDrawer, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, ENROLL_NOW_COURSE_STARTING_SOON_LABEL, ENROLL_NOW_LABEL, EditAlertDialog, EducationBox, EducationDialog, EducationTab, EdxIframeContext, EmptyStats, ExperienceBox, ExperienceDialog, ExperienceTab, FacetFilterContext, Footer, GradebookTab, GroupsFilterDropdown, INVITATION_ONLY_LABEL, InstitutionDialog, IntegrationsTab, InviteUserContent, InviteUserDialog, InvitedUsersDialog, LOCAL_MODELS, Loader, LocalLLMTab, LocalModelsContent, LoginButton, MACOS_PERMISSIONS_COMMANDS, MEMORY_PAGE_SIZE, Markdown, MinimumMentorAlert, MonetizationTab, NotificationDisplay, NotificationDropdown, ONBOARDING_SECTORS, OnboardingShell, OnboardingWizard, PLATFORM_AUDIT_DEEP_PAGING_THRESHOLD, PLATFORM_AUDIT_PAGE_SIZE, PaywallModal, PlacementExam, PlacementExamsDropdown, PlatformAuditLogDetailSheet, PlatformNavbar, PlatformNavbarSearch, Profile, ProfileTimeChart, ProgressDots, ProjectActionButtons, ProjectFilesModal, ProjectInstructionsModal, ProjectLandingPage, ProjectMentorsList, ProjectsPage, REQUEST_ACCESS_COURSE_STARTING_SOON_LABEL, REQUEST_ACCESS_LABEL, RenameProjectModal, ResumeBox, ResumeTab, RichTextEditor, SUPPORTED_LOCALES, SandboxConfig, SearchableMultiSelect, SendNotificationDialog, SignupButton, SkeletonActivityStatBox, SkeletonAddSkillsLoading, SkeletonCreatePathwaySearchList, SkeletonDiscoverFilterBox, SkeletonEducationBox, SkeletonMultiplier, SkeletonPathwayBox, SkeletonProfileInfoCard, SkeletonSkillBox, SkillBox, SkillDetailModal, SkillLeaderboardChart, SkillsBox, SkillsList, SlashSkillPicker, Spinner, StatCard, StepHeader, TAURI_COMMANDS, TAURI_EVENTS, TenantSwitcher, TimeFilter, TimeTrackingProvider, TimedExam, ToolDialogs, TopBanner, UpgradePackageModal, UserAvatar, Version, WebContainersI18nProvider, WorkflowSidebar, addBookmarksTab, availablePlacementExams, findLastResumeBlock, findSequentialParent, flattenVerticalBlocks, formatAuditTimestamp, formatTimeZoneLabel, getCatalog, getFirstAvailableUnit, getLocalLLMModel, getLocalLLMToolSupport, getNextUnitIframe, getOrg, getParentBlockById, getParentsInfosFromSublessonId, getPreviousUnitIframe, getRandomCourseImage, getSectorById, getTenant, getUnitToIframe, getUserId, getUserName, humanizeAuditToken, inBrowserPrint, inIframe, initialCuaDriverInstallState, initialModelDownloadState, isCoworkEnabled, isLocalLLMEnabled, isPlatformNavbarCreditBalanceVisible, isSlashCommandToken, isTauriApp, isValidLocale, isValidTimeZone, components as markdownComponents, modelSupportsCowork, onboardingPrimaryButtonClass, onboardingSecondaryButtonClass, resolveAuditTimeZone, resolveCreateAgentLabels, sanitizeCss, setCoworkEnabled, setLocalLLMEnabled, setLocalLLMModel, setLocalLLMToolSupport, smallestCoworkModel, useAnalyticsScope, useAnalyticsSettings, useAuditLog, useCatalogSearch, useChartFilters, useChatPrivacy, useChatState, useCourseDetail, useCourseMetadata, useCourses, useCuaDriver, useDiscover, useEdxIframe, useFinancial, useIframeMessageHandler, useLocalStorage, useMemory, useModelDownload, useMonetization, useOverview, usePlatformAuditLabels, usePlatformAuditLog, useProfileActivityStats, useProfileCredentials, useProfilePathways, useProfilePrograms, useProfileSkills, useProfileTimeSpent, usePrograms, useReports, useScopedMentorDbId, useScopedMentorId, useSlashSkillPicker, useSlashSkills, useT, useTauri, useTimeTracking, useTopics, useTranscripts, useUserCourses, useUserMetadata, useUsers, useWebContainersI18n, useWebContainersLocale };
237309
237473
  //# sourceMappingURL=index.esm.js.map
@@ -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,
@@ -218650,6 +218686,129 @@ function getPayloadConfigFromPayload(config, payload, key) {
218650
218686
 
218651
218687
  React__default.createContext(undefined);
218652
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
+
218653
218812
  Array.from({ length: 24 }, (_, i) => i);
218654
218813
 
218655
218814
  /**
@@ -253186,126 +253345,6 @@ function SheetDescription({ className, ...props }) {
253186
253345
  return (jsx(DialogPrimitive.Description, { "data-slot": "sheet-description", className: cn('text-muted-foreground text-sm', className), ...props }));
253187
253346
  }
253188
253347
 
253189
- /**
253190
- * Core agent search hook — thin wrapper around `useGetAiSearchMentorsQuery`.
253191
- *
253192
- * This is the low-level building block. For a higher-level hook that manages
253193
- * search state, debounce, and pagination controls, use
253194
- * `useAgentSearchWithPagination`.
253195
- */
253196
- function useAgentSearch({ tenantKey, query, limit = 6, offset, starred, featured, category, subjects, llm, types, includeMainPublicMentors, orderDirection, skip = false, }) {
253197
- var _a, _b, _c;
253198
- const { data, isLoading, isFetching, refetch } = useGetAiSearchMentorsQuery({
253199
- platform_key: tenantKey,
253200
- query: query || undefined,
253201
- limit,
253202
- ...(offset !== undefined && { offset }),
253203
- ...(starred !== undefined && { starred }),
253204
- ...(featured !== undefined && { featured }),
253205
- ...(category && { category }),
253206
- ...(subjects && { subjects }),
253207
- ...(llm && { llm }),
253208
- ...(types && { types }),
253209
- ...(includeMainPublicMentors !== undefined && {
253210
- include_main_public_mentors: includeMainPublicMentors,
253211
- }),
253212
- ...(orderDirection && { order_direction: orderDirection }),
253213
- }, { skip: skip || !tenantKey });
253214
- return {
253215
- agents: ((_a = data === null || data === void 0 ? void 0 : data.results) !== null && _a !== void 0 ? _a : []),
253216
- facets: data === null || data === void 0 ? void 0 : data.facets,
253217
- hasMore: !!(data === null || data === void 0 ? void 0 : data.next),
253218
- totalCount: (_b = data === null || data === void 0 ? void 0 : data.count) !== null && _b !== void 0 ? _b : 0,
253219
- totalPages: (_c = data === null || data === void 0 ? void 0 : data.total_pages) !== null && _c !== void 0 ? _c : 0,
253220
- isLoading,
253221
- isFetching,
253222
- refetch,
253223
- };
253224
- }
253225
-
253226
- 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]}
253227
-
253228
- /**
253229
- * Higher-level agent search hook that manages search state, debounce, and
253230
- * pagination controls on top of `useAgentSearch`.
253231
- *
253232
- * Use this for simple list/table views (MyMentorsModal, SettingsModal).
253233
- * For the full explore page with sections, use `useAgentSearch` directly.
253234
- */
253235
- function useAgentSearchWithPagination({ itemsPerPage = 6, paginationMode = 'paginated', debounceMs = 500, ...queryConfig }) {
253236
- const [searchQuery, setSearchQuery] = React__default.useState('');
253237
- const [debouncedQuery] = a$3(searchQuery, debounceMs);
253238
- const [currentPage, setCurrentPage] = React__default.useState(1);
253239
- const [infiniteLimit, setInfiniteLimit] = React__default.useState(itemsPerPage);
253240
- // Reset pagination when search changes
253241
- React__default.useEffect(() => {
253242
- setCurrentPage(1);
253243
- setInfiniteLimit(itemsPerPage);
253244
- }, [debouncedQuery, itemsPerPage]);
253245
- const isPaginated = paginationMode === 'paginated';
253246
- const result = useAgentSearch({
253247
- ...queryConfig,
253248
- query: debouncedQuery,
253249
- limit: isPaginated ? itemsPerPage : infiniteLimit,
253250
- offset: isPaginated ? (currentPage - 1) * itemsPerPage : undefined,
253251
- });
253252
- const totalPages = Math.ceil(result.totalCount / itemsPerPage);
253253
- const handlePageChange = React__default.useCallback((page) => {
253254
- setCurrentPage(page);
253255
- }, []);
253256
- const loadMore = React__default.useCallback(() => {
253257
- setInfiniteLimit((prev) => prev + itemsPerPage);
253258
- }, [itemsPerPage]);
253259
- return {
253260
- ...result,
253261
- searchQuery,
253262
- setSearchQuery,
253263
- debouncedQuery,
253264
- currentPage,
253265
- totalPages,
253266
- handlePageChange,
253267
- loadMore,
253268
- };
253269
- }
253270
-
253271
- /**
253272
- * Hook for starring / un-starring agents.
253273
- *
253274
- * Extracted so the star logic can be shared by any component that renders
253275
- * agent cards with a favorite toggle.
253276
- */
253277
- function useAgentStar({ tenantKey, username, onUnauthenticatedAction, }) {
253278
- const [starAgent] = useStarMentorMutation();
253279
- const [unstarAgent] = useUnstarMentorMutation();
253280
- const [togglingAgentId, setTogglingAgentId] = React__default.useState(null);
253281
- const toggleFavorite = React__default.useCallback(async (agent, event) => {
253282
- event.stopPropagation();
253283
- if (!username) {
253284
- onUnauthenticatedAction === null || onUnauthenticatedAction === void 0 ? void 0 : onUnauthenticatedAction();
253285
- return;
253286
- }
253287
- if (!tenantKey)
253288
- return;
253289
- setTogglingAgentId(String(agent.id));
253290
- try {
253291
- const mutation = agent.starred ? unstarAgent : starAgent;
253292
- await mutation({
253293
- org: tenantKey,
253294
- // @ts-expect-error userId param type mismatch in data-layer
253295
- userId: username,
253296
- mentor: agent.unique_id || '',
253297
- }).unwrap();
253298
- }
253299
- catch (error) {
253300
- console.error('Error toggling favorite:', error);
253301
- }
253302
- finally {
253303
- setTogglingAgentId(null);
253304
- }
253305
- }, [username, tenantKey, starAgent, unstarAgent, onUnauthenticatedAction]);
253306
- return { toggleFavorite, togglingAgentId };
253307
- }
253308
-
253309
253348
  function MentorSelectionGrid({ selectedMentorIds, onMentorSelect, searchQuery, onSearchChange, tenantKey, itemsPerPage = 8, showSearch = true, minHeight = '400px', }) {
253310
253349
  const t = useT();
253311
253350
  const { agents: mentors, isLoading: isMentorsLoading, isFetching: isMentorsFetching, currentPage, totalPages, setSearchQuery: setMentorSearch, handlePageChange, } = useAgentSearchWithPagination({ tenantKey, itemsPerPage });
@@ -267938,6 +267977,13 @@ function ConnectorManagementContent({ tenantKey, username, mentorId, rbacPermiss
267938
267977
  }).unwrap();
267939
267978
  if (!result.auth_url)
267940
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;
267941
267987
  const popup = window.open(result.auth_url, '_blank');
267942
267988
  // Create connection using helper function
267943
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.16",
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.12",
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",