@iblai/iblai-js 2.28.1 → 2.29.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.
@@ -2,7 +2,7 @@ import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import React__default, { useState, useEffect, forwardRef, createElement as createElement$1, useLayoutEffect, createContext, useContext, useMemo, useReducer, useRef, useImperativeHandle, useCallback, isValidElement, Children, PureComponent, cloneElement, Component as Component$1, useDebugValue, Fragment as Fragment$2, useId as useId$2, lazy, Suspense } from 'react';
4
4
  import * as dataLayer from '@iblai/data-layer';
5
- import { useGetUserMetadataQuery, useGetUserMetadataEdxQuery, useGetUserProfileSummaryQuery, useUpdateUserMetadataMutation, useUpdateUserMetadataEdxMutation, useUploadProfileImageMutation, useResetPasswordMutation, useSelfRetireMutation, useCreateUserInstitutionMutation, useGetUserInstitutionsQuery, useCreateUserEducationMutation, useUpdateUserEducationMutation, useDeleteUserEducationMutation, useGetUserEducationQuery, useCreateUserCompanyMutation, useGetUserCompaniesQuery, useCreateUserExperienceMutation, useUpdateUserExperienceMutation, useDeleteUserExperienceMutation, useGetUserExperienceQuery, useGetUserResumeQuery, useCreateUserResumeMutation, useGetMySubscriptionsQuery, useGetItemSubscriptionQuery, useCancelSubscriptionMutation, useGetLearnerCourseOutlineQuery, getSections, findResumeBlock, flattenOutline, normalizeLearnerCompletionError, useGetLearnerDetailsQuery, useGetUserEnrolledCoursesQuery, useGetUserEnrolledProgramsQuery, useGetUserCatalogPathwaysQuery, useGetUsersAsAssertionsQuery, useGetUserEarnedSkillsQuery, useGetUserReportedSkillsQuery, useGetUserDesiredSkillsQuery, useCreateGlobalMemoryMutation, useUpdateGlobalMemoryMutation, useUpdateMentorMemoryMutation, useGetMemsearchStatusQuery, useGetUserMemorySettingsQuery, useUpdateUserMemorySettingsMutation, useGetGlobalMemoriesQuery, useGetAllMentorMemoriesQuery, useDeleteGlobalMemoryMutation, useDeleteMentorMemoryMutation, useUpdateArtifactMutation, useLazyGetArtifactVersionQuery, useLazyListArtifactVersionsQuery, useSetCurrentVersionMutation, useListArtifactVersionsQuery, useLazyGetArtifactQuery, useLazyListArtifactsQuery, useEditSessionMutation, useListArtifactsQuery, useLazyGetSessionIdQuery, useGetAiSearchMentorsQuery, useStarMentorMutation, useUnstarMentorMutation, useGetUserChatHistoryReportsQuery, USER_CHAT_HISTORY_REPORT_ACTIVE_STATES, useCreateUserChatHistoryReportMutation, useLazyGetDownloadReportFromURLQuery, useGetUserChatHistoryReportStatusQuery, userChatHistoryApiSlice, USER_CHAT_HISTORY_QUERY_KEYS, useGetUserChatHistoryQuery, useGetUserChatHistoryFilterQuery, useGetMentorsQuery, useGetUserChatHistorySessionQuery, useUserLlmUsageSummary, useUserLlmSpendOverTime, useUserLlmCostByModel, useUserLlmCostByService, useUserLlmRecentActivity, USER_LLM_RECENT_ACTIVITY_PAGE_SIZE, useUserLlmTraceObservations, useInviteUserMutation, usePlatformInvitationsQuery, useCreateCatalogInvitationCourseBulkMutation, useGetCatalogInvitationsCourseQuery, useLazyPlatformUsersQuery, useLazyPlatformUserGroupsQuery, useGetPersonnalizedSearchQuery, useCreateCatalogInvitationProgramBulkMutation, useGetCatalogInvitationsProgramQuery, useGetVectorDocumentsQuery, useGetLlmsQuery, useUpdateUserRoleMutation, useUpdateUserStatusMutation, useUpdatePlatformUserRoleWithPoliciesMutation, usePlatformUsersQuery, useGetAccessibleUsersQuery, isPoliciesResponse, platformApiSlice, featureTags, useLazyGetRbacTeamsAccessListQuery, useCreateRbacTeamsAccessMutation, useGetRbacGroupsQuery, usePlatformUserGroupsQuery, useCreateRbacGroupMutation, useUpdateRbacGroupMutation, useDeleteRbacGroupMutation, useCreatePlatformUserGroupMutation, useUpdatePlatformUserGroupMutation, useDeletePlatformUserGroupMutation, useGetRbacGroupDetailsQuery, useGetPlatformUserGroupDetailsQuery, useGetRbacPermissionsMutation, useGetRbacRolesQuery, useCreateRbacRoleMutation, useUpdateRbacRoleMutation, useDeleteRbacRoleMutation, useGetRbacRoleDetailsQuery, useGetRbacActionsDefinitionQuery, useGetRbacResourceDiscoveryQuery, useGetRbacResourceListQuery, useGetRbacPoliciesQuery, useCreateRbacPolicyMutation, useUpdateRbacPolicyMutation, useDeleteRbacPolicyMutation, useGetRbacPolicyDetailsQuery, useGetWatchedGroupsQuery, useCreateWatchedGroupMutation, useUpdateWatchedGroupMutation, useDeleteWatchedGroupMutation, useAddWatchedUserMutation, useRemoveWatchedUserMutation, useAddWatcherMutation, useUpdateWatcherMutation, useDeleteWatcherMutation, useGetWatchedUsersQuery, useGetWatchersQuery, WATCHER_NOTIFICATION_EVENTS, WATCHER_NOTIFICATION_EVENT_LABELS, useGetApplicationFormsQuery, useGetApplicationFormDetailQuery, useCreateApplicationFormMutation, useUpdateApplicationFormMutation, useGetApplicationAdminDetailQuery, useInviteApplicationCandidateMutation, useLazyGetApplicationAttachmentFileQuery, useCreateApplicationWaiverMutation, useDeleteApplicationWaiverMutation, useSubmitApplicationOverrideMutation, useUpdateApplicationPlacementMutation, useDeleteApplicationCourseAssignmentMutation, useCreateApplicationNoteMutation, useUpdateApplicationNoteMutation, useDeleteApplicationNoteMutation, useTransitionApplicationMutation, useLinkApplicationCandidateMutation, useCreateApplicationPlacementsMutation, useGetCustomMentorsQuery, useCreateApplicationCourseAssignmentsMutation, useGetApplicationBlocksQuery, useDeleteApplicationBlockMutation, useGetApplicationsPipelineStatsQuery, useGetApplicationsPipelineQuery, useGetTenantMetadataQuery, useUpdateTenantMetadataMutation, useLazyGetTenantMetadataQuery, useDeleteApiKeyMutation, useGetApiKeyQuery, useGetApiKeyFieldPermissionsQuery, useUpdateApiKeyMutation, useGetApiKeysQuery, unwrapApiTokenList, useCreateApiKeyMutation, useCreateLLMCredentialMutation, useGetCredentialsSchemaQuery, useGetMaskedLLMCredentialsQuery, useDeleteIntegrationCredentialMutation, useDeleteCredentialMutation, useCreateIntegrationCredentialMutation, useGetIntegrationCredentialsSchemaQuery, useGetMaskedIntegrationCredentialsQuery, useGetAccountBillingInfoQuery, useUpdateAutoRechargeInfoMutation, useTriggerAutoRechargeMutation, useGetAgentSpendCapQuery, useGetTenantSpendCapQuery, useListAgentUserSpendCapsQuery, useUpsertAgentSpendCapMutation, useDeleteAgentSpendCapMutation, useUpsertTenantSpendCapMutation, useDeleteTenantSpendCapMutation, useUpsertUserSpendCapMutation, useDeleteUserSpendCapMutation, useGetLlmUsageMetricsQuery, useListAgentSpendCapsQuery, useGetCreditTransactionsQuery, useCreateStripeCustomerPortalMutation, useSetPlatformConfigurationsMutation, useGetPlatformConfigurationsQuery, useUpdatePlatformMembershipMutation, useGetPlatformMembershipQuery, VERCEL_SPA, useGetCustomDomainsQuery, useGetHostingProjectsQuery, useCreateCustomDomainMutation, useDeleteCustomDomainMutation, useCreateHostingProjectDomainMutation, useUpdateHostingDomainMutation, useDeleteHostingDomainMutation, useGetStudentMentorCreationStatusQuery, useSetStudentMentorCreationStatusMutation, coreApiSlice, recommendationPromptTypeEnum, useGetRecommendedPromptsListQuery, useCreateRecommendedPromptMutation, useUpdateRecommendedPromptMutation, useDeleteRecommendedPromptMutation, useLazyGetPublicPlatformImageAssetFileUrlQuery, useCreatePlatformImageAssetMutation, useGetProviderConfigQuery, useCreateProviderConfigMutation, useDeleteProviderConfigMutation, useGetExternalMappingQuery, useGetCredentialsListQuery, useCreateExternalMappingMutation, useDeleteExternalMappingMutation, useGetMemsearchConfigQuery, useUpdateMemsearchConfigMutation, useGetStripeConnectStatusQuery, useStartStripeConnectOnboardingMutation, useLazyGetStripeConnectDashboardQuery, useListPaywallsQuery, useListPricesQuery, useCreatePriceMutation, useUpdatePriceMutation, useDeletePriceMutation, useGetPaywallConfigQuery, useEnablePaywallMutation, useUpdatePaywallMutation, useGetMentorMemoriesListQuery, useGetMemoryCategoriesAdminQuery, useCreateMentorMemoryMutation, splitHostPortInput, validateHostPort, useCreateVirtualMachineNetworkPolicyMutation, useUpdateVirtualMachineNetworkPolicyMutation, VIRTUAL_MACHINE_MAX_POLICY_HOSTS, getVirtualMachineApiError, useDeleteVirtualMachineNetworkPolicyMutation, extractBoundMentorIds, useCreateVirtualMachineSecretMutation, useUpdateVirtualMachineSecretMutation, VIRTUAL_MACHINE_SECRET_VALUE_MIN_LENGTH, VIRTUAL_MACHINE_ENV_VAR_PATTERN, useDeleteVirtualMachineSecretMutation, useGetIntegrationCredentialsQuery, useListVirtualMachineNetworkPoliciesQuery, useListVirtualMachineSecretsQuery, getVirtualMachineErrorStatus, useLazyGetCourseMetaDataQuery, useLazyGetCourseCompletionOutlinesQuery, useLazyGetCourseEligibilityQuery, useLazyGetEdxSSOTokenQuery, useCreateCourseEnrollmentMutation, useCreateStripeCheckoutSessionMutation, useLazyGetCourseProgressQuery, useLazyGetCourseCompletionQuery, useUpdateExamAttemptMutation, useStartExamMutation, useLazyGetExamInfoQuery, useGetAgentSkillResourcesQuery, useCreateAgentSkillResourceMutation, useUpdateAgentSkillResourceMutation, useUploadAgentSkillResourceAssetMutation, useDeleteAgentSkillResourceMutation, useGetMentorSkillAssignmentsQuery, useGetAgentSkillsQuery, useCreateMentorSkillAssignmentMutation, useUpdateMentorSkillAssignmentMutation, useDeleteMentorSkillAssignmentMutation, useCreateAgentSkillMutation, useUpdateAgentSkillMutation, useDeleteAgentSkillMutation, filterSlashSkills, useGetMentorSkillAssignmentsInfiniteQuery, MENTOR_SKILL_ASSIGNMENTS_PAGE_SIZE, useUpdateUserProjectMutation, useGetTrainingDocumentsQuery, useLazyGetConnectedServiceAuthUrlQuery, useCreateUserProjectMutation, useDeleteUserProjectMutation, useGetUserProjectDetailsQuery, useEditTrainingDocumentMutation, useAddTrainingDocumentMutation, useLazyGetCredentialsQuery, useGetMentorSettingsQuery, useEditMentorMutation, useUploadLightLogoMutation, useUploadDarkLogoMutation, useUpdatePlatformInfoMutation, LOGO_ENDPOINTS, useCreateEvalDatasetMutation, useAddEvalDatasetItemsMutation, useUploadEvalDatasetCsvMutation, useDeleteEvalDatasetItemMutation, useListEvalDatasetItemsQuery, evalTotalPages, useListEvalDatasetsQuery, useGetUserProjectsQuery, useCreateSessionIdMutation, useGetMentorCategoriesQuery, useGetTenantChatPrivacyConfigQuery as useGetTenantChatPrivacyConfigQuery$1, useGetCallConfigurationsQuery, useCreateCallConfigurationMutation, useUpdateCallConfigurationMutation, chatPrivacyApiSlice, useDeleteMentorMutation, useForkMentorMutation, useGetToolsQuery, useLazyGetMCPServersQuery, useOauthFindMutation, useLazyStartOAuthFlowQuery, useCreateMCPServerMutation, usePartialUpdateMCPServerMutation, useCreateMCPServerConnectionMutation, usePatchMCPServerConnectionMutation, useGetConnectedServicesQuery, useGetMCPServersQuery, useGetMCPServerConnectionsQuery, useUpdateMCPServerMutation, useDeleteMCPServerMutation, useEditMentorJsonMutation, useDisconnectServiceMutation, useGetPromptCategoriesQuery, PRIVACY_ACTIONS, PRIVACY_ENTITY_TYPES, useGetVoicesQuery, useGetVoiceQuery, isBaseAgentMentor, useGetGradeResultQuery, useOverrideGradeResultMutation, useGetChatHistoryFilterQuery, useListGradeResultsQuery, useGetMentorGraderConfigurationQuery, useListGraderCriteriaQuery, useCreateMentorGraderConfigurationMutation, useUpdateMentorGraderConfigurationMutation, useCreateGraderCriterionMutation, useUpdateGraderCriterionMutation, useDeleteGraderCriterionMutation, useGetSpendCapStatusQuery, useGetMentorPublicSettingsQuery, useGetChatHistoryQuery, useGetMentorSummariesQuery, useGetConversationMemoriesQuery, useGetSupportTicketsQuery, useGetSupportTicketMessagesQuery, useCreateSupportTicketMessageMutation, usePatchSupportTicketMutation, useCloseSupportTicketMutation, useCreateLtiMentorMutation, useUpdateLtiMentorMutation, useGetLtiMentorsQuery, useDeleteLtiMentorMutation, useCreateLtiKeyMutation, useUpdateLtiKeyMutation, useDeleteLtiKeyMutation, useGetLtiKeysQuery, useCreateLtiToolMutation, useUpdateLtiToolMutation, useGetLtiToolsQuery, useGetPlatformInfoQuery, useCreatePromptMutation, useGetPromptsSearchQuery, useUpdatePromptMutation, useCreateRedirectTokenMutation, useGetShareableLinkQuery, useCreateShareableLinkMutation, useUpdateShareableLinkMutation, useCreateDisclaimerMutation, useUpdateDisclaimerMutation, useGetDisclaimersQuery, useUpdateRbacMentorAccessMutation, useGetRbacMentorAccessListQuery, useStartEvalRunMutation, useEvaluateEvalRunMutation, useGetEvalRunQuery, useDeleteEvalScoreMutation, useListEvalRunJudgesQuery, useCreateEvalScoreMutation, useDeleteEvalRunMutation, useExportEvalRunMutation, useListEvalRunsQuery, useLazyGetEvalRunQuery, evaluationsApiSlice, EVALUATIONS_TAGS, useGetPersonnalizedMentorsQuery, useCreateCallCredentialsMutation, useGetGuidedPromptsQuery, useUpdateChatSessionSharedMutation, useUpdateMessageFeedbackMutation, useLazyGetPromptsSearchQuery, useLazyGetGuidedPromptsQuery, useGetPublicMentorsQuery, useGetPeriodicAgentsQuery, useGetPeriodicAgentLogsListQuery, useCreatePeriodicAgentMutation, useDeletePeriodicAgentMutation, useCreateMemoryCategoryMutation, useUpdateMemoryCategoryMutation, useDeleteMemoryCategoryMutation, useDeletePromptMutation, useDeleteTrainingDocumentMutation, useGetTrainingDocumentRetrainScheduleQuery, useCreateTrainingDocumentRetrainScheduleMutation, useGetDisclaimerAgreementsQuery } from '@iblai/data-layer';
5
+ import { useGetUserMetadataQuery, useGetUserMetadataEdxQuery, useGetUserProfileSummaryQuery, useUpdateUserMetadataMutation, useUpdateUserMetadataEdxMutation, useUploadProfileImageMutation, useResetPasswordMutation, useSelfRetireMutation, useCreateUserInstitutionMutation, useGetUserInstitutionsQuery, useCreateUserEducationMutation, useUpdateUserEducationMutation, useDeleteUserEducationMutation, useGetUserEducationQuery, useCreateUserCompanyMutation, useGetUserCompaniesQuery, useCreateUserExperienceMutation, useUpdateUserExperienceMutation, useDeleteUserExperienceMutation, useGetUserExperienceQuery, useGetUserResumeQuery, useCreateUserResumeMutation, useGetMySubscriptionsQuery, useGetItemSubscriptionQuery, useCancelSubscriptionMutation, useGetLearnerCourseOutlineQuery, getSections, findResumeBlock, flattenOutline, normalizeLearnerCompletionError, useGetLearnerDetailsQuery, useGetUserEnrolledCoursesQuery, useGetUserEnrolledProgramsQuery, useGetUserCatalogPathwaysQuery, useGetUsersAsAssertionsQuery, useGetUserEarnedSkillsQuery, useGetUserReportedSkillsQuery, useGetUserDesiredSkillsQuery, useCreateGlobalMemoryMutation, useUpdateGlobalMemoryMutation, useUpdateMentorMemoryMutation, useGetMemsearchStatusQuery, useGetUserMemorySettingsQuery, useUpdateUserMemorySettingsMutation, useGetGlobalMemoriesQuery, useGetAllMentorMemoriesQuery, useDeleteGlobalMemoryMutation, useDeleteMentorMemoryMutation, useUpdateArtifactMutation, useLazyGetArtifactVersionQuery, useLazyListArtifactVersionsQuery, useSetCurrentVersionMutation, useListArtifactVersionsQuery, useLazyGetArtifactQuery, useLazyListArtifactsQuery, useEditSessionMutation, useListArtifactsQuery, useLazyGetSessionIdQuery, useGetAiSearchMentorsQuery, useStarMentorMutation, useUnstarMentorMutation, useGetUserChatHistoryReportsQuery, USER_CHAT_HISTORY_REPORT_ACTIVE_STATES, useCreateUserChatHistoryReportMutation, useLazyGetDownloadReportFromURLQuery, useGetUserChatHistoryReportStatusQuery, userChatHistoryApiSlice, USER_CHAT_HISTORY_QUERY_KEYS, useGetUserChatHistoryQuery, useGetUserChatHistoryFilterQuery, useGetMentorsQuery, useGetUserChatHistorySessionQuery, useUserLlmUsageSummary, useUserLlmSpendOverTime, useUserLlmCostByModel, useUserLlmRecentActivity, USER_LLM_RECENT_ACTIVITY_PAGE_SIZE, useUserLlmTraceObservations, useInviteUserMutation, usePlatformInvitationsQuery, useCreateCatalogInvitationCourseBulkMutation, useGetCatalogInvitationsCourseQuery, useLazyPlatformUsersQuery, useLazyPlatformUserGroupsQuery, useGetPersonnalizedSearchQuery, useCreateCatalogInvitationProgramBulkMutation, useGetCatalogInvitationsProgramQuery, useGetVectorDocumentsQuery, useGetLlmsQuery, useUpdateUserRoleMutation, useUpdateUserStatusMutation, useUpdatePlatformUserRoleWithPoliciesMutation, usePlatformUsersQuery, useGetAccessibleUsersQuery, isPoliciesResponse, platformApiSlice, featureTags, useLazyGetRbacTeamsAccessListQuery, useCreateRbacTeamsAccessMutation, useGetRbacGroupsQuery, usePlatformUserGroupsQuery, useCreateRbacGroupMutation, useUpdateRbacGroupMutation, useDeleteRbacGroupMutation, useCreatePlatformUserGroupMutation, useUpdatePlatformUserGroupMutation, useDeletePlatformUserGroupMutation, useGetRbacGroupDetailsQuery, useGetPlatformUserGroupDetailsQuery, useGetRbacPermissionsMutation, useGetRbacRolesQuery, useCreateRbacRoleMutation, useUpdateRbacRoleMutation, useDeleteRbacRoleMutation, useGetRbacRoleDetailsQuery, useGetRbacActionsDefinitionQuery, useGetRbacResourceDiscoveryQuery, useGetRbacResourceListQuery, useGetRbacPoliciesQuery, useCreateRbacPolicyMutation, useUpdateRbacPolicyMutation, useDeleteRbacPolicyMutation, useGetRbacPolicyDetailsQuery, useGetWatchedGroupsQuery, useCreateWatchedGroupMutation, useUpdateWatchedGroupMutation, useDeleteWatchedGroupMutation, useAddWatchedUserMutation, useRemoveWatchedUserMutation, useAddWatcherMutation, useUpdateWatcherMutation, useDeleteWatcherMutation, useGetWatchedUsersQuery, useGetWatchersQuery, WATCHER_NOTIFICATION_EVENTS, WATCHER_NOTIFICATION_EVENT_LABELS, useGetApplicationFormsQuery, useGetApplicationFormDetailQuery, useCreateApplicationFormMutation, useUpdateApplicationFormMutation, useGetApplicationAdminDetailQuery, useInviteApplicationCandidateMutation, useLazyGetApplicationAttachmentFileQuery, useCreateApplicationWaiverMutation, useDeleteApplicationWaiverMutation, useSubmitApplicationOverrideMutation, useUpdateApplicationPlacementMutation, useDeleteApplicationCourseAssignmentMutation, useCreateApplicationNoteMutation, useUpdateApplicationNoteMutation, useDeleteApplicationNoteMutation, useTransitionApplicationMutation, useLinkApplicationCandidateMutation, useCreateApplicationPlacementsMutation, useGetCustomMentorsQuery, useCreateApplicationCourseAssignmentsMutation, useGetApplicationBlocksQuery, useDeleteApplicationBlockMutation, useGetApplicationsPipelineStatsQuery, useGetApplicationsPipelineQuery, useGetTenantMetadataQuery, useUpdateTenantMetadataMutation, useLazyGetTenantMetadataQuery, useDeleteApiKeyMutation, useGetApiKeyQuery, useGetApiKeyFieldPermissionsQuery, useUpdateApiKeyMutation, useGetApiKeysQuery, unwrapApiTokenList, useCreateApiKeyMutation, useCreateLLMCredentialMutation, useGetCredentialsSchemaQuery, useGetMaskedLLMCredentialsQuery, useDeleteIntegrationCredentialMutation, useDeleteCredentialMutation, useCreateIntegrationCredentialMutation, useGetIntegrationCredentialsSchemaQuery, useGetMaskedIntegrationCredentialsQuery, useGetAccountBillingInfoQuery, useUpdateAutoRechargeInfoMutation, useTriggerAutoRechargeMutation, useGetAgentSpendCapQuery, useGetTenantSpendCapQuery, useListAgentUserSpendCapsQuery, useUpsertAgentSpendCapMutation, useDeleteAgentSpendCapMutation, useUpsertTenantSpendCapMutation, useDeleteTenantSpendCapMutation, useUpsertUserSpendCapMutation, useDeleteUserSpendCapMutation, useGetLlmUsageMetricsQuery, useListAgentSpendCapsQuery, useGetCreditTransactionsQuery, useCreateStripeCustomerPortalMutation, useSetPlatformConfigurationsMutation, useGetPlatformConfigurationsQuery, useUpdatePlatformMembershipMutation, useGetPlatformMembershipQuery, VERCEL_SPA, useGetCustomDomainsQuery, useGetHostingProjectsQuery, useCreateCustomDomainMutation, useDeleteCustomDomainMutation, useCreateHostingProjectDomainMutation, useUpdateHostingDomainMutation, useDeleteHostingDomainMutation, useGetStudentMentorCreationStatusQuery, useSetStudentMentorCreationStatusMutation, coreApiSlice, recommendationPromptTypeEnum, useGetRecommendedPromptsListQuery, useCreateRecommendedPromptMutation, useUpdateRecommendedPromptMutation, useDeleteRecommendedPromptMutation, useLazyGetPublicPlatformImageAssetFileUrlQuery, useCreatePlatformImageAssetMutation, useGetProviderConfigQuery, useCreateProviderConfigMutation, useDeleteProviderConfigMutation, useGetExternalMappingQuery, useGetCredentialsListQuery, useCreateExternalMappingMutation, useDeleteExternalMappingMutation, useGetMemsearchConfigQuery, useUpdateMemsearchConfigMutation, useGetStripeConnectStatusQuery, useStartStripeConnectOnboardingMutation, useLazyGetStripeConnectDashboardQuery, useListPaywallsQuery, useListPricesQuery, useCreatePriceMutation, useUpdatePriceMutation, useDeletePriceMutation, useGetPaywallConfigQuery, useEnablePaywallMutation, useUpdatePaywallMutation, useGetMentorMemoriesListQuery, useGetMemoryCategoriesAdminQuery, useCreateMentorMemoryMutation, splitHostPortInput, validateHostPort, useCreateVirtualMachineNetworkPolicyMutation, useUpdateVirtualMachineNetworkPolicyMutation, VIRTUAL_MACHINE_MAX_POLICY_HOSTS, getVirtualMachineApiError, useDeleteVirtualMachineNetworkPolicyMutation, extractBoundMentorIds, useCreateVirtualMachineSecretMutation, useUpdateVirtualMachineSecretMutation, VIRTUAL_MACHINE_SECRET_VALUE_MIN_LENGTH, VIRTUAL_MACHINE_ENV_VAR_PATTERN, useDeleteVirtualMachineSecretMutation, useGetIntegrationCredentialsQuery, useListVirtualMachineNetworkPoliciesQuery, useListVirtualMachineSecretsQuery, getVirtualMachineErrorStatus, useLazyGetCourseMetaDataQuery, useLazyGetCourseCompletionOutlinesQuery, useLazyGetCourseEligibilityQuery, useLazyGetEdxSSOTokenQuery, useCreateCourseEnrollmentMutation, useCreateStripeCheckoutSessionMutation, useLazyGetCourseProgressQuery, useLazyGetCourseCompletionQuery, useUpdateExamAttemptMutation, useStartExamMutation, useLazyGetExamInfoQuery, useGetAgentSkillResourcesQuery, useCreateAgentSkillResourceMutation, useUpdateAgentSkillResourceMutation, useUploadAgentSkillResourceAssetMutation, useDeleteAgentSkillResourceMutation, useGetMentorSkillAssignmentsQuery, useGetAgentSkillsQuery, useCreateMentorSkillAssignmentMutation, useUpdateMentorSkillAssignmentMutation, useDeleteMentorSkillAssignmentMutation, useCreateAgentSkillMutation, useUpdateAgentSkillMutation, useDeleteAgentSkillMutation, filterSlashSkills, useGetMentorSkillAssignmentsInfiniteQuery, MENTOR_SKILL_ASSIGNMENTS_PAGE_SIZE, useUpdateUserProjectMutation, useGetTrainingDocumentsQuery, useLazyGetConnectedServiceAuthUrlQuery, useCreateUserProjectMutation, useDeleteUserProjectMutation, useGetUserProjectDetailsQuery, useEditTrainingDocumentMutation, useAddTrainingDocumentMutation, useLazyGetCredentialsQuery, useGetMentorSettingsQuery, useEditMentorMutation, useUploadLightLogoMutation, useUploadDarkLogoMutation, useUpdatePlatformInfoMutation, LOGO_ENDPOINTS, useCreateEvalDatasetMutation, useAddEvalDatasetItemsMutation, useUploadEvalDatasetCsvMutation, useDeleteEvalDatasetItemMutation, useListEvalDatasetItemsQuery, evalTotalPages, useListEvalDatasetsQuery, useGetUserProjectsQuery, useCreateSessionIdMutation, useGetMentorCategoriesQuery, useGetTenantChatPrivacyConfigQuery as useGetTenantChatPrivacyConfigQuery$1, useGetCallConfigurationsQuery, useCreateCallConfigurationMutation, useUpdateCallConfigurationMutation, chatPrivacyApiSlice, useDeleteMentorMutation, useForkMentorMutation, useGetToolsQuery, useLazyGetMCPServersQuery, useOauthFindMutation, useLazyStartOAuthFlowQuery, useCreateMCPServerMutation, usePartialUpdateMCPServerMutation, useCreateMCPServerConnectionMutation, usePatchMCPServerConnectionMutation, useGetConnectedServicesQuery, useGetMCPServersQuery, useGetMCPServerConnectionsQuery, useUpdateMCPServerMutation, useDeleteMCPServerMutation, useEditMentorJsonMutation, useDisconnectServiceMutation, useGetPromptCategoriesQuery, PRIVACY_ACTIONS, PRIVACY_ENTITY_TYPES, useGetVoicesQuery, useGetVoiceQuery, isBaseAgentMentor, useGetGradeResultQuery, useOverrideGradeResultMutation, useGetChatHistoryFilterQuery, useListGradeResultsQuery, useGetMentorGraderConfigurationQuery, useListGraderCriteriaQuery, useCreateMentorGraderConfigurationMutation, useUpdateMentorGraderConfigurationMutation, useCreateGraderCriterionMutation, useUpdateGraderCriterionMutation, useDeleteGraderCriterionMutation, useGetSpendCapStatusQuery, useGetMentorPublicSettingsQuery, useGetChatHistoryQuery, useGetMentorSummariesQuery, useGetConversationMemoriesQuery, useGetSupportTicketsQuery, useGetSupportTicketMessagesQuery, useCreateSupportTicketMessageMutation, usePatchSupportTicketMutation, useCloseSupportTicketMutation, useCreateLtiMentorMutation, useUpdateLtiMentorMutation, useGetLtiMentorsQuery, useDeleteLtiMentorMutation, useCreateLtiKeyMutation, useUpdateLtiKeyMutation, useDeleteLtiKeyMutation, useGetLtiKeysQuery, useCreateLtiToolMutation, useUpdateLtiToolMutation, useGetLtiToolsQuery, useGetPlatformInfoQuery, useCreatePromptMutation, useGetPromptsSearchQuery, useUpdatePromptMutation, useCreateRedirectTokenMutation, useGetShareableLinkQuery, useCreateShareableLinkMutation, useUpdateShareableLinkMutation, useCreateDisclaimerMutation, useUpdateDisclaimerMutation, useGetDisclaimersQuery, useUpdateRbacMentorAccessMutation, useGetRbacMentorAccessListQuery, useStartEvalRunMutation, useEvaluateEvalRunMutation, useGetEvalRunQuery, useDeleteEvalScoreMutation, useListEvalRunJudgesQuery, useCreateEvalScoreMutation, useDeleteEvalRunMutation, useExportEvalRunMutation, useListEvalRunsQuery, useLazyGetEvalRunQuery, evaluationsApiSlice, EVALUATIONS_TAGS, useGetPersonnalizedMentorsQuery, useCreateCallCredentialsMutation, useGetGuidedPromptsQuery, useUpdateChatSessionSharedMutation, useUpdateMessageFeedbackMutation, useLazyGetPromptsSearchQuery, useLazyGetGuidedPromptsQuery, useGetPublicMentorsQuery, useGetPeriodicAgentsQuery, useGetPeriodicAgentLogsListQuery, useCreatePeriodicAgentMutation, useDeletePeriodicAgentMutation, useCreateMemoryCategoryMutation, useUpdateMemoryCategoryMutation, useDeleteMemoryCategoryMutation, useDeletePromptMutation, useDeleteTrainingDocumentMutation, useGetTrainingDocumentRetrainScheduleQuery, useCreateTrainingDocumentRetrainScheduleMutation, useGetDisclaimerAgreementsQuery } from '@iblai/data-layer';
6
6
  import { removeAuthItem, setAuthItem, isTauriEmbeddedLLMHost, selectRbacPermissions, useCurrentTenant, canViewOtherUsersChatHistory, isPureWatcher, getInitials, useTenantMetadata, useUsername, selectStreaming, isLoggedIn, TOOL_NAME_MAP, WRITE_TODOS_TOOL, WithPermissions, canWriteField, useStripeUpgrade, openExternalUrl, CHAT_AREA_SIZE, isAlphaNumeric32, checkRbacPermission, selectNumberOfActiveChatMessages, TOOLS, hasRemoteAiConfig, isSafariBrowser, useShowAttachment, useShowVoiceCall, useShowVoiceRecorder, useMentorSettings, selectShowingSharedChat, useShowFreeTrialDialog, useEmbedMode, chatInputSliceSelectors, useResponsive, useAccessingPublicRoute, useVisitingTenant, useModelFileUploadCapabilities, useChatFileUpload, useVoiceChat, selectAttachedFiles, MENTOR_CHAT_DOCUMENTS_EXTENSIONS, removeFile, chatInputSliceActions, chatActions, WithFormPermissions, useTenantContext, TimeTracker, advancedTabsProperties, defaultSessionIds, pickWritableFields, ANONYMOUS_USERNAME as ANONYMOUS_USERNAME$3, redirectToAuthSpaJoinTenant, selectActiveTab, useAxdToken, useWelcomeMessage, markdownToPlainText, useCachedSessionId, use402ErrorCheck, use401TokenRefresh, selectTokenEnabled, selectToken, useServiceWorker, useUserAgreement, useAdvancedChat, sendMessageToParentWebsite, useMentorTools, useFileDragDrop, eventBus, RemoteEvents, selectEnableChatActionsPopup, advancedTabs, isInIframe, getAuthSpaJoinUrl, addMessage, clearFiles, MENTOR_VISIBILITY } from '@iblai/web-utils';
7
7
  import { useDispatch, useSelector } from 'react-redux';
8
8
  import { toast } from 'sonner';
@@ -1885,7 +1885,7 @@ const formatRelativeLocale = {
1885
1885
  other: "P",
1886
1886
  };
1887
1887
 
1888
- const formatRelative = (token, _date, _baseDate, _options) =>
1888
+ const formatRelative$1 = (token, _date, _baseDate, _options) =>
1889
1889
  formatRelativeLocale[token];
1890
1890
 
1891
1891
  /**
@@ -2358,7 +2358,7 @@ const enUS = {
2358
2358
  code: "en-US",
2359
2359
  formatDistance: formatDistance$1,
2360
2360
  formatLong: formatLong,
2361
- formatRelative: formatRelative,
2361
+ formatRelative: formatRelative$1,
2362
2362
  localize: localize,
2363
2363
  match: match,
2364
2364
  options: {
@@ -96482,6 +96482,16 @@ var advancedPlatformMembership$3 = {
96482
96482
  switchEnabled: "enabled",
96483
96483
  switchDisabled: "disabled"
96484
96484
  };
96485
+ var advancedSeoDiscoverability$3 = {
96486
+ toastUpdateSuccess: "SEO discoverability setting updated successfully",
96487
+ toastUpdateError: "Failed to update SEO discoverability setting",
96488
+ label: "SEO Discoverability",
96489
+ infoAriaLabel: "More info about SEO discoverability",
96490
+ infoTooltip: "Make this organization's public course, program, and pathway pages crawlable by search engines and AI, and include them in the sitemap.",
96491
+ switchAriaLabel: "SEO discoverability",
96492
+ switchEnabled: "enabled",
96493
+ switchDisabled: "disabled"
96494
+ };
96485
96495
  var advancedProviderConfig$3 = {
96486
96496
  regionAriaLabel: "Provider Configuration",
96487
96497
  sectionTitle: "Provider Configuration",
@@ -100051,7 +100061,10 @@ var profileIndex$3 = {
100051
100061
  groupRecords: "Records",
100052
100062
  descLlmUsagePreview: "Spend, tokens and requests across conversations.",
100053
100063
  sectionFeatures: "Features",
100054
- tooltipDisplayMentorAI: "Keeps the AI agent panel beside whatever you are working on, so you can ask questions without leaving the page."
100064
+ tooltipDisplayMentorAI: "Keeps the AI agent panel beside whatever you are working on, so you can ask questions without leaving the page.",
100065
+ tabOverview: "Overview",
100066
+ descOverview: "Your courses, conversations, AI usage and memory, all in one place.",
100067
+ descOverviewPreview: "Courses, conversations, AI usage and memory, all in one place."
100055
100068
  };
100056
100069
  var profileInviteUserContent$3 = {
100057
100070
  inviteUsersTitle: "Invite Users",
@@ -103126,8 +103139,6 @@ var profileLlmUsage$3 = {
103126
103139
  colCost: "Cost",
103127
103140
  byModelTitle: "By model",
103128
103141
  byModelSubtitle: "Share of your spend per model",
103129
- byServiceTitle: "By service",
103130
- byServiceSubtitle: "Where your spend comes from",
103131
103142
  otherRow: "Other",
103132
103143
  unknownModel: "Unknown model",
103133
103144
  unknownService: "Other service",
@@ -103169,6 +103180,82 @@ var profileLlmUsage$3 = {
103169
103180
  tryAgain: "Try again",
103170
103181
  scopeUser: "Usage for {username}"
103171
103182
  };
103183
+ var profileOverviewTab$3 = {
103184
+ scopeSelf: "Your activity across courses and AI agents, at a glance.",
103185
+ scopeUser: "Activity for {username}",
103186
+ refresh: "Refresh overview",
103187
+ unavailable: "Unavailable",
103188
+ kpiEnrolled: "Enrolled courses",
103189
+ kpiEnrolledSub: "{count} in progress",
103190
+ kpiEnrolledSubAll: "All time",
103191
+ kpiCompleted: "Completed courses",
103192
+ kpiCompletedSub: "{percent}% of enrolled",
103193
+ kpiProgress: "Average progress",
103194
+ kpiProgressSub: "Across enrolled courses",
103195
+ kpiTimeSpent: "Time spent",
103196
+ kpiTimeSpentSub: "Learning time, all courses",
103197
+ kpiConversations: "Conversations",
103198
+ kpiConversationsSub: "With AI agents",
103199
+ kpiConversationsLast: "Last one {when}",
103200
+ kpiSpend: "AI spend",
103201
+ kpiSpendSub: "Last 30 days",
103202
+ kpiRequests: "AI requests",
103203
+ kpiRequestsSub: "{tokens} tokens, last 30 days",
103204
+ kpiMemories: "Memories",
103205
+ kpiMemoriesSub: "Saved by the AI",
103206
+ kpiMemoriesSubOn: "Auto-capture on",
103207
+ kpiMemoriesSubOff: "Auto-capture off",
103208
+ recordsLabel: "Records",
103209
+ recordsCredentials: "{count, plural, one {# credential} other {# credentials}}",
103210
+ recordsPrograms: "{count, plural, one {# program} other {# programs}}",
103211
+ recordsPathways: "{count, plural, one {# pathway} other {# pathways}}",
103212
+ learningTitle: "Learning progress",
103213
+ learningSubtitle: "Where each enrolled course stands",
103214
+ learningError: "Course enrollments couldn't be loaded.",
103215
+ learningEmpty: "No course enrollments yet.",
103216
+ learningProgressUnavailable: "Progress details aren't available for this account.",
103217
+ moreCourses: "{count, plural, one {# more course in the gradebook} other {# more courses in the gradebook}}",
103218
+ legendCompleted: "Completed",
103219
+ legendInProgress: "In progress",
103220
+ legendNotStarted: "Not started",
103221
+ ringAria: "{completed} of {total} courses completed",
103222
+ viewProgress: "View progress for {name}",
103223
+ courseProgressAria: "{name}: {percent}% complete",
103224
+ courseCompleted: "Completed",
103225
+ coursePassed: "Passed",
103226
+ courseEnrolledOn: "Enrolled {date}",
103227
+ courseTimeSpent: "{duration} spent",
103228
+ enrollmentActive: "Active",
103229
+ enrollmentInactive: "Inactive",
103230
+ viewGradebook: "View gradebook",
103231
+ viewUsage: "View usage",
103232
+ viewHistory: "View history",
103233
+ viewMemory: "View memory",
103234
+ usageTitle: "AI usage",
103235
+ usageSubtitle: "Daily spend over the last 30 days",
103236
+ usageForbidden: "AI usage isn't available for this account.",
103237
+ usageError: "AI usage couldn't be loaded.",
103238
+ usageEmpty: "No AI usage in the last 30 days.",
103239
+ usageNoSpend: "No spend recorded in the last 30 days.",
103240
+ conversationsTitle: "Recent conversations",
103241
+ conversationsSubtitle: "Your latest exchanges with AI agents",
103242
+ conversationsSubtitlePreview: "Latest exchanges with AI agents",
103243
+ conversationsForbidden: "Conversations aren't available for this account.",
103244
+ conversationsError: "Conversations couldn't be loaded.",
103245
+ conversationsEmpty: "No conversations yet.",
103246
+ conversation: "Conversation",
103247
+ agent: "AI agent",
103248
+ messageCount: "{count, plural, one {# message} other {# messages}}",
103249
+ memoryTitle: "Memory",
103250
+ memorySubtitle: "What the AI remembers about you",
103251
+ memorySubtitlePreview: "What the AI remembers",
103252
+ memoryError: "Memories couldn't be loaded.",
103253
+ memoryEmpty: "No memories saved yet.",
103254
+ memoryAutoCapture: "Auto-capture",
103255
+ memoryUseInResponses: "Used in responses",
103256
+ stateOn: "On",
103257
+ stateOff: "Off"
103258
+ };
103172
103259
  var virtualMachineHostInput$3 = {
103173
103260
  listLabel: "Allowed Hosts",
103174
103261
  removeHost: "Remove {host}",
@@ -103355,6 +103442,7 @@ var en = {
103355
103442
  advancedExternalMapping: advancedExternalMapping$3,
103356
103443
  advancedMemsearchConfig: advancedMemsearchConfig$3,
103357
103444
  advancedPlatformMembership: advancedPlatformMembership$3,
103445
+ advancedSeoDiscoverability: advancedSeoDiscoverability$3,
103358
103446
  advancedProviderConfig: advancedProviderConfig$3,
103359
103447
  advancedRecommendationSystemPrompts: advancedRecommendationSystemPrompts$3,
103360
103448
  advancedSmtp: advancedSmtp$3,
@@ -103629,6 +103717,7 @@ var en = {
103629
103717
  analyticsLlmUsage: analyticsLlmUsage$3,
103630
103718
  analyticsTraces: analyticsTraces$3,
103631
103719
  profileLlmUsage: profileLlmUsage$3,
103720
+ profileOverviewTab: profileOverviewTab$3,
103632
103721
  virtualMachineHostInput: virtualMachineHostInput$3,
103633
103722
  virtualMachineAdminTab: virtualMachineAdminTab$3,
103634
103723
  virtualMachineNetworkPolicies: virtualMachineNetworkPolicies$3,
@@ -104049,6 +104138,16 @@ var advancedPlatformMembership$2 = {
104049
104138
  switchEnabled: "activée",
104050
104139
  switchDisabled: "désactivée"
104051
104140
  };
104141
+ var advancedSeoDiscoverability$2 = {
104142
+ toastUpdateSuccess: "Paramètre de découvrabilité SEO mis à jour avec succès",
104143
+ toastUpdateError: "Échec de la mise à jour du paramètre de découvrabilité SEO",
104144
+ label: "Découvrabilité SEO",
104145
+ infoAriaLabel: "Plus d'informations sur la découvrabilité SEO",
104146
+ infoTooltip: "Rendre les pages publiques de cours, programmes et parcours de cette organisation explorables par les moteurs de recherche et l'IA, et les inclure dans le plan du site.",
104147
+ switchAriaLabel: "Découvrabilité SEO",
104148
+ switchEnabled: "activée",
104149
+ switchDisabled: "désactivée"
104150
+ };
104052
104151
  var advancedProviderConfig$2 = {
104053
104152
  regionAriaLabel: "Configuration du fournisseur",
104054
104153
  sectionTitle: "Configuration du fournisseur",
@@ -107784,7 +107883,10 @@ var profileIndex$2 = {
107784
107883
  groupRecords: "Dossiers",
107785
107884
  descLlmUsagePreview: "Dépenses, jetons et requêtes dans les conversations.",
107786
107885
  sectionFeatures: "Fonctionnalités",
107787
- tooltipDisplayMentorAI: "Garde le panneau de l'agent IA à côté de ce que vous faites, pour poser des questions sans quitter la page."
107886
+ tooltipDisplayMentorAI: "Garde le panneau de l'agent IA à côté de ce que vous faites, pour poser des questions sans quitter la page.",
107887
+ tabOverview: "Vue d'ensemble",
107888
+ descOverview: "Vos cours, conversations, utilisation de l'IA et mémoire, réunis au même endroit.",
107889
+ descOverviewPreview: "Cours, conversations, utilisation de l'IA et mémoire, réunis au même endroit."
107788
107890
  };
107789
107891
  var profileInviteUserContent$2 = {
107790
107892
  inviteUsersTitle: "Inviter des utilisateurs",
@@ -110693,8 +110795,6 @@ var profileLlmUsage$2 = {
110693
110795
  colCost: "Coût",
110694
110796
  byModelTitle: "Par modèle",
110695
110797
  byModelSubtitle: "Part de vos dépenses par modèle",
110696
- byServiceTitle: "Par service",
110697
- byServiceSubtitle: "D'où viennent vos dépenses",
110698
110798
  otherRow: "Autres",
110699
110799
  unknownModel: "Modèle inconnu",
110700
110800
  unknownService: "Autre service",
@@ -110736,6 +110836,82 @@ var profileLlmUsage$2 = {
110736
110836
  tryAgain: "Réessayer",
110737
110837
  scopeUser: "Utilisation de {username}"
110738
110838
  };
110839
+ var profileOverviewTab$2 = {
110840
+ scopeSelf: "Votre activité dans les cours et avec les agents IA, en un coup d'œil.",
110841
+ scopeUser: "Activité de {username}",
110842
+ refresh: "Actualiser la vue d'ensemble",
110843
+ unavailable: "Indisponible",
110844
+ kpiEnrolled: "Cours suivis",
110845
+ kpiEnrolledSub: "{count} en cours",
110846
+ kpiEnrolledSubAll: "Depuis le début",
110847
+ kpiCompleted: "Cours terminés",
110848
+ kpiCompletedSub: "{percent}% des cours suivis",
110849
+ kpiProgress: "Progression moyenne",
110850
+ kpiProgressSub: "Sur l'ensemble des cours suivis",
110851
+ kpiTimeSpent: "Temps passé",
110852
+ kpiTimeSpentSub: "Temps d'apprentissage, tous cours confondus",
110853
+ kpiConversations: "Conversations",
110854
+ kpiConversationsSub: "Avec des agents IA",
110855
+ kpiConversationsLast: "La dernière {when}",
110856
+ kpiSpend: "Dépenses IA",
110857
+ kpiSpendSub: "30 derniers jours",
110858
+ kpiRequests: "Requêtes IA",
110859
+ kpiRequestsSub: "{tokens} jetons, 30 derniers jours",
110860
+ kpiMemories: "Souvenirs",
110861
+ kpiMemoriesSub: "Enregistrés par l'IA",
110862
+ kpiMemoriesSubOn: "Capture automatique activée",
110863
+ kpiMemoriesSubOff: "Capture automatique désactivée",
110864
+ recordsLabel: "Dossiers",
110865
+ recordsCredentials: "{count, plural, one {# certification} other {# certifications}}",
110866
+ recordsPrograms: "{count, plural, one {# programme} other {# programmes}}",
110867
+ recordsPathways: "{count, plural, one {# parcours} other {# parcours}}",
110868
+ learningTitle: "Progression d'apprentissage",
110869
+ learningSubtitle: "Où en est chaque cours suivi",
110870
+ learningError: "Impossible de charger les inscriptions aux cours.",
110871
+ learningEmpty: "Aucune inscription à un cours pour le moment.",
110872
+ learningProgressUnavailable: "Les détails de progression ne sont pas disponibles pour ce compte.",
110873
+ moreCourses: "{count, plural, one {# autre cours dans le carnet de notes} other {# autres cours dans le carnet de notes}}",
110874
+ legendCompleted: "Terminés",
110875
+ legendInProgress: "En cours",
110876
+ legendNotStarted: "Non commencés",
110877
+ ringAria: "{completed} cours terminés sur {total}",
110878
+ viewProgress: "Voir la progression de {name}",
110879
+ courseProgressAria: "{name} : {percent}% terminé",
110880
+ courseCompleted: "Terminé",
110881
+ coursePassed: "Réussi",
110882
+ courseEnrolledOn: "Inscrit le {date}",
110883
+ courseTimeSpent: "{duration} passées",
110884
+ enrollmentActive: "Active",
110885
+ enrollmentInactive: "Inactive",
110886
+ viewGradebook: "Voir le carnet de notes",
110887
+ viewUsage: "Voir l'utilisation",
110888
+ viewHistory: "Voir l'historique",
110889
+ viewMemory: "Voir la mémoire",
110890
+ usageTitle: "Utilisation de l'IA",
110891
+ usageSubtitle: "Dépenses quotidiennes sur les 30 derniers jours",
110892
+ usageForbidden: "L'utilisation de l'IA n'est pas disponible pour ce compte.",
110893
+ usageError: "Impossible de charger l'utilisation de l'IA.",
110894
+ usageEmpty: "Aucune utilisation de l'IA au cours des 30 derniers jours.",
110895
+ usageNoSpend: "Aucune dépense enregistrée au cours des 30 derniers jours.",
110896
+ conversationsTitle: "Conversations récentes",
110897
+ conversationsSubtitle: "Vos derniers échanges avec des agents IA",
110898
+ conversationsSubtitlePreview: "Derniers échanges avec des agents IA",
110899
+ conversationsForbidden: "Les conversations ne sont pas disponibles pour ce compte.",
110900
+ conversationsError: "Impossible de charger les conversations.",
110901
+ conversationsEmpty: "Aucune conversation pour le moment.",
110902
+ conversation: "Conversation",
110903
+ agent: "Agent IA",
110904
+ messageCount: "{count, plural, one {# message} other {# messages}}",
110905
+ memoryTitle: "Mémoire",
110906
+ memorySubtitle: "Ce que l'IA retient de vous",
110907
+ memorySubtitlePreview: "Ce que l'IA retient",
110908
+ memoryError: "Impossible de charger les souvenirs.",
110909
+ memoryEmpty: "Aucun souvenir enregistré pour le moment.",
110910
+ memoryAutoCapture: "Capture automatique",
110911
+ memoryUseInResponses: "Utilisée dans les réponses",
110912
+ stateOn: "Activé",
110913
+ stateOff: "Désactivé"
110914
+ };
110739
110915
  var virtualMachineHostInput$2 = {
110740
110916
  listLabel: "Hôtes autorisés",
110741
110917
  removeHost: "Retirer {host}",
@@ -110922,6 +111098,7 @@ var fr = {
110922
111098
  advancedExternalMapping: advancedExternalMapping$2,
110923
111099
  advancedMemsearchConfig: advancedMemsearchConfig$2,
110924
111100
  advancedPlatformMembership: advancedPlatformMembership$2,
111101
+ advancedSeoDiscoverability: advancedSeoDiscoverability$2,
110925
111102
  advancedProviderConfig: advancedProviderConfig$2,
110926
111103
  advancedRecommendationSystemPrompts: advancedRecommendationSystemPrompts$2,
110927
111104
  advancedSmtp: advancedSmtp$2,
@@ -111196,6 +111373,7 @@ var fr = {
111196
111373
  analyticsLlmUsage: analyticsLlmUsage$2,
111197
111374
  analyticsTraces: analyticsTraces$2,
111198
111375
  profileLlmUsage: profileLlmUsage$2,
111376
+ profileOverviewTab: profileOverviewTab$2,
111199
111377
  virtualMachineHostInput: virtualMachineHostInput$2,
111200
111378
  virtualMachineAdminTab: virtualMachineAdminTab$2,
111201
111379
  virtualMachineNetworkPolicies: virtualMachineNetworkPolicies$2,
@@ -111616,6 +111794,16 @@ var advancedPlatformMembership$1 = {
111616
111794
  switchEnabled: "habilitado",
111617
111795
  switchDisabled: "deshabilitado"
111618
111796
  };
111797
+ var advancedSeoDiscoverability$1 = {
111798
+ toastUpdateSuccess: "Configuración de descubrimiento SEO actualizada correctamente",
111799
+ toastUpdateError: "Error al actualizar la configuración de descubrimiento SEO",
111800
+ label: "Descubrimiento SEO",
111801
+ infoAriaLabel: "Más información sobre el descubrimiento SEO",
111802
+ infoTooltip: "Hacer que las páginas públicas de cursos, programas y rutas de esta organización sean rastreables por los motores de búsqueda y la IA, e incluirlas en el mapa del sitio.",
111803
+ switchAriaLabel: "Descubrimiento SEO",
111804
+ switchEnabled: "habilitado",
111805
+ switchDisabled: "deshabilitado"
111806
+ };
111619
111807
  var advancedProviderConfig$1 = {
111620
111808
  regionAriaLabel: "Configuración del proveedor",
111621
111809
  sectionTitle: "Configuración del proveedor",
@@ -115351,7 +115539,10 @@ var profileIndex$1 = {
115351
115539
  groupRecords: "Registros",
115352
115540
  descLlmUsagePreview: "Gasto, tokens y solicitudes en las conversaciones.",
115353
115541
  sectionFeatures: "Funciones",
115354
- tooltipDisplayMentorAI: "Mantiene el panel del agente de IA junto a lo que estés haciendo, para que puedas preguntar sin salir de la página."
115542
+ tooltipDisplayMentorAI: "Mantiene el panel del agente de IA junto a lo que estés haciendo, para que puedas preguntar sin salir de la página.",
115543
+ tabOverview: "Resumen",
115544
+ descOverview: "Tus cursos, conversaciones, uso de IA y memoria, todo en un solo lugar.",
115545
+ descOverviewPreview: "Cursos, conversaciones, uso de IA y memoria, todo en un solo lugar."
115355
115546
  };
115356
115547
  var profileInviteUserContent$1 = {
115357
115548
  inviteUsersTitle: "Invitar usuarios",
@@ -118260,8 +118451,6 @@ var profileLlmUsage$1 = {
118260
118451
  colCost: "Costo",
118261
118452
  byModelTitle: "Por modelo",
118262
118453
  byModelSubtitle: "Parte de tu gasto por modelo",
118263
- byServiceTitle: "Por servicio",
118264
- byServiceSubtitle: "De dónde proviene tu gasto",
118265
118454
  otherRow: "Otros",
118266
118455
  unknownModel: "Modelo desconocido",
118267
118456
  unknownService: "Otro servicio",
@@ -118303,6 +118492,82 @@ var profileLlmUsage$1 = {
118303
118492
  tryAgain: "Intentar de nuevo",
118304
118493
  scopeUser: "Uso de {username}"
118305
118494
  };
118495
+ var profileOverviewTab$1 = {
118496
+ scopeSelf: "Tu actividad en cursos y agentes de IA, de un vistazo.",
118497
+ scopeUser: "Actividad de {username}",
118498
+ refresh: "Actualizar resumen",
118499
+ unavailable: "No disponible",
118500
+ kpiEnrolled: "Cursos inscritos",
118501
+ kpiEnrolledSub: "{count} en curso",
118502
+ kpiEnrolledSubAll: "Desde siempre",
118503
+ kpiCompleted: "Cursos completados",
118504
+ kpiCompletedSub: "{percent}% de los inscritos",
118505
+ kpiProgress: "Progreso medio",
118506
+ kpiProgressSub: "En todos los cursos inscritos",
118507
+ kpiTimeSpent: "Tiempo dedicado",
118508
+ kpiTimeSpentSub: "Tiempo de aprendizaje, todos los cursos",
118509
+ kpiConversations: "Conversaciones",
118510
+ kpiConversationsSub: "Con agentes de IA",
118511
+ kpiConversationsLast: "La última {when}",
118512
+ kpiSpend: "Gasto en IA",
118513
+ kpiSpendSub: "Últimos 30 días",
118514
+ kpiRequests: "Solicitudes de IA",
118515
+ kpiRequestsSub: "{tokens} tokens, últimos 30 días",
118516
+ kpiMemories: "Memorias",
118517
+ kpiMemoriesSub: "Guardadas por la IA",
118518
+ kpiMemoriesSubOn: "Captura automática activada",
118519
+ kpiMemoriesSubOff: "Captura automática desactivada",
118520
+ recordsLabel: "Registros",
118521
+ recordsCredentials: "{count, plural, one {# credencial} other {# credenciales}}",
118522
+ recordsPrograms: "{count, plural, one {# programa} other {# programas}}",
118523
+ recordsPathways: "{count, plural, one {# itinerario} other {# itinerarios}}",
118524
+ learningTitle: "Progreso de aprendizaje",
118525
+ learningSubtitle: "Estado de cada curso inscrito",
118526
+ learningError: "No se pudieron cargar las inscripciones a cursos.",
118527
+ learningEmpty: "Aún no hay inscripciones a cursos.",
118528
+ learningProgressUnavailable: "Los detalles de progreso no están disponibles para esta cuenta.",
118529
+ moreCourses: "{count, plural, one {# curso más en el libro de calificaciones} other {# cursos más en el libro de calificaciones}}",
118530
+ legendCompleted: "Completados",
118531
+ legendInProgress: "En curso",
118532
+ legendNotStarted: "Sin empezar",
118533
+ ringAria: "{completed} de {total} cursos completados",
118534
+ viewProgress: "Ver el progreso de {name}",
118535
+ courseProgressAria: "{name}: {percent}% completado",
118536
+ courseCompleted: "Completado",
118537
+ coursePassed: "Aprobado",
118538
+ courseEnrolledOn: "Inscrito el {date}",
118539
+ courseTimeSpent: "{duration} dedicados",
118540
+ enrollmentActive: "Activa",
118541
+ enrollmentInactive: "Inactiva",
118542
+ viewGradebook: "Ver calificaciones",
118543
+ viewUsage: "Ver uso",
118544
+ viewHistory: "Ver historial",
118545
+ viewMemory: "Ver memoria",
118546
+ usageTitle: "Uso de IA",
118547
+ usageSubtitle: "Gasto diario en los últimos 30 días",
118548
+ usageForbidden: "El uso de IA no está disponible para esta cuenta.",
118549
+ usageError: "No se pudo cargar el uso de IA.",
118550
+ usageEmpty: "Sin uso de IA en los últimos 30 días.",
118551
+ usageNoSpend: "Sin gasto registrado en los últimos 30 días.",
118552
+ conversationsTitle: "Conversaciones recientes",
118553
+ conversationsSubtitle: "Tus últimos intercambios con agentes de IA",
118554
+ conversationsSubtitlePreview: "Últimos intercambios con agentes de IA",
118555
+ conversationsForbidden: "Las conversaciones no están disponibles para esta cuenta.",
118556
+ conversationsError: "No se pudieron cargar las conversaciones.",
118557
+ conversationsEmpty: "Aún no hay conversaciones.",
118558
+ conversation: "Conversación",
118559
+ agent: "Agente de IA",
118560
+ messageCount: "{count, plural, one {# mensaje} other {# mensajes}}",
118561
+ memoryTitle: "Memoria",
118562
+ memorySubtitle: "Lo que la IA recuerda de ti",
118563
+ memorySubtitlePreview: "Lo que la IA recuerda",
118564
+ memoryError: "No se pudieron cargar las memorias.",
118565
+ memoryEmpty: "Aún no hay memorias guardadas.",
118566
+ memoryAutoCapture: "Captura automática",
118567
+ memoryUseInResponses: "Usada en las respuestas",
118568
+ stateOn: "Activado",
118569
+ stateOff: "Desactivado"
118570
+ };
118306
118571
  var virtualMachineHostInput$1 = {
118307
118572
  listLabel: "Hosts permitidos",
118308
118573
  removeHost: "Quitar {host}",
@@ -118489,6 +118754,7 @@ var es = {
118489
118754
  advancedExternalMapping: advancedExternalMapping$1,
118490
118755
  advancedMemsearchConfig: advancedMemsearchConfig$1,
118491
118756
  advancedPlatformMembership: advancedPlatformMembership$1,
118757
+ advancedSeoDiscoverability: advancedSeoDiscoverability$1,
118492
118758
  advancedProviderConfig: advancedProviderConfig$1,
118493
118759
  advancedRecommendationSystemPrompts: advancedRecommendationSystemPrompts$1,
118494
118760
  advancedSmtp: advancedSmtp$1,
@@ -118763,6 +119029,7 @@ var es = {
118763
119029
  analyticsLlmUsage: analyticsLlmUsage$1,
118764
119030
  analyticsTraces: analyticsTraces$1,
118765
119031
  profileLlmUsage: profileLlmUsage$1,
119032
+ profileOverviewTab: profileOverviewTab$1,
118766
119033
  virtualMachineHostInput: virtualMachineHostInput$1,
118767
119034
  virtualMachineAdminTab: virtualMachineAdminTab$1,
118768
119035
  virtualMachineNetworkPolicies: virtualMachineNetworkPolicies$1,
@@ -119183,6 +119450,16 @@ var advancedPlatformMembership = {
119183
119450
  switchEnabled: "已启用",
119184
119451
  switchDisabled: "已禁用"
119185
119452
  };
119453
+ var advancedSeoDiscoverability = {
119454
+ toastUpdateSuccess: "SEO 可发现性设置已成功更新",
119455
+ toastUpdateError: "更新 SEO 可发现性设置失败",
119456
+ label: "SEO 可发现性",
119457
+ infoAriaLabel: "更多关于 SEO 可发现性的信息",
119458
+ infoTooltip: "使该组织的公开课程、项目和学习路径页面可被搜索引擎和 AI 抓取,并包含在站点地图中。",
119459
+ switchAriaLabel: "SEO 可发现性",
119460
+ switchEnabled: "已启用",
119461
+ switchDisabled: "已禁用"
119462
+ };
119186
119463
  var advancedProviderConfig = {
119187
119464
  regionAriaLabel: "提供商配置",
119188
119465
  sectionTitle: "提供商配置",
@@ -122918,7 +123195,10 @@ var profileIndex = {
122918
123195
  groupRecords: "记录",
122919
123196
  descLlmUsagePreview: "各对话中的花费、令牌数和请求数。",
122920
123197
  sectionFeatures: "功能",
122921
- tooltipDisplayMentorAI: "让 AI 助手面板始终显示在当前页面旁边,无需离开页面即可提问。"
123198
+ tooltipDisplayMentorAI: "让 AI 助手面板始终显示在当前页面旁边,无需离开页面即可提问。",
123199
+ tabOverview: "概览",
123200
+ descOverview: "您的课程、对话、AI 用量和记忆,尽在一处。",
123201
+ descOverviewPreview: "课程、对话、AI 用量和记忆,尽在一处。"
122922
123202
  };
122923
123203
  var profileInviteUserContent = {
122924
123204
  inviteUsersTitle: "邀请用户",
@@ -125827,8 +126107,6 @@ var profileLlmUsage = {
125827
126107
  colCost: "花费",
125828
126108
  byModelTitle: "按模型",
125829
126109
  byModelSubtitle: "各模型占你花费的比例",
125830
- byServiceTitle: "按服务",
125831
- byServiceSubtitle: "你的花费来自哪里",
125832
126110
  otherRow: "其他",
125833
126111
  unknownModel: "未知模型",
125834
126112
  unknownService: "其他服务",
@@ -125870,6 +126148,82 @@ var profileLlmUsage = {
125870
126148
  tryAgain: "重试",
125871
126149
  scopeUser: "{username} 的用量"
125872
126150
  };
126151
+ var profileOverviewTab = {
126152
+ scopeSelf: "一览您在课程和 AI 代理中的活动。",
126153
+ scopeUser: "{username} 的活动",
126154
+ refresh: "刷新概览",
126155
+ unavailable: "不可用",
126156
+ kpiEnrolled: "已注册课程",
126157
+ kpiEnrolledSub: "{count} 门进行中",
126158
+ kpiEnrolledSubAll: "全部时间",
126159
+ kpiCompleted: "已完成课程",
126160
+ kpiCompletedSub: "占已注册课程的 {percent}%",
126161
+ kpiProgress: "平均进度",
126162
+ kpiProgressSub: "所有已注册课程",
126163
+ kpiTimeSpent: "学习时长",
126164
+ kpiTimeSpentSub: "所有课程的学习时间",
126165
+ kpiConversations: "对话",
126166
+ kpiConversationsSub: "与 AI 代理",
126167
+ kpiConversationsLast: "最近一次 {when}",
126168
+ kpiSpend: "AI 花费",
126169
+ kpiSpendSub: "最近 30 天",
126170
+ kpiRequests: "AI 请求",
126171
+ kpiRequestsSub: "{tokens} 个令牌,最近 30 天",
126172
+ kpiMemories: "记忆",
126173
+ kpiMemoriesSub: "由 AI 保存",
126174
+ kpiMemoriesSubOn: "自动捕获已开启",
126175
+ kpiMemoriesSubOff: "自动捕获已关闭",
126176
+ recordsLabel: "记录",
126177
+ recordsCredentials: "{count, plural, other {# 项证书}}",
126178
+ recordsPrograms: "{count, plural, other {# 个项目}}",
126179
+ recordsPathways: "{count, plural, other {# 条路径}}",
126180
+ learningTitle: "学习进度",
126181
+ learningSubtitle: "每门已注册课程的进展",
126182
+ learningError: "无法加载课程注册信息。",
126183
+ learningEmpty: "尚未注册任何课程。",
126184
+ learningProgressUnavailable: "此账户的进度详情不可用。",
126185
+ moreCourses: "{count, plural, other {成绩册中还有 # 门课程}}",
126186
+ legendCompleted: "已完成",
126187
+ legendInProgress: "进行中",
126188
+ legendNotStarted: "未开始",
126189
+ ringAria: "已完成 {total} 门课程中的 {completed} 门",
126190
+ viewProgress: "查看 {name} 的进度",
126191
+ courseProgressAria: "{name}:已完成 {percent}%",
126192
+ courseCompleted: "已完成",
126193
+ coursePassed: "已通过",
126194
+ courseEnrolledOn: "注册于 {date}",
126195
+ courseTimeSpent: "已学习 {duration}",
126196
+ enrollmentActive: "进行中",
126197
+ enrollmentInactive: "未激活",
126198
+ viewGradebook: "查看成绩册",
126199
+ viewUsage: "查看用量",
126200
+ viewHistory: "查看历史",
126201
+ viewMemory: "查看记忆",
126202
+ usageTitle: "AI 用量",
126203
+ usageSubtitle: "最近 30 天的每日花费",
126204
+ usageForbidden: "此账户的 AI 用量不可用。",
126205
+ usageError: "无法加载 AI 用量。",
126206
+ usageEmpty: "最近 30 天没有 AI 用量。",
126207
+ usageNoSpend: "最近 30 天没有记录到花费。",
126208
+ conversationsTitle: "最近对话",
126209
+ conversationsSubtitle: "您与 AI 代理的最新交流",
126210
+ conversationsSubtitlePreview: "与 AI 代理的最新交流",
126211
+ conversationsForbidden: "此账户的对话不可用。",
126212
+ conversationsError: "无法加载对话。",
126213
+ conversationsEmpty: "尚无对话。",
126214
+ conversation: "对话",
126215
+ agent: "AI 代理",
126216
+ messageCount: "{count, plural, other {# 条消息}}",
126217
+ memoryTitle: "记忆",
126218
+ memorySubtitle: "AI 对您的记忆",
126219
+ memorySubtitlePreview: "AI 的记忆",
126220
+ memoryError: "无法加载记忆。",
126221
+ memoryEmpty: "尚未保存任何记忆。",
126222
+ memoryAutoCapture: "自动捕获",
126223
+ memoryUseInResponses: "用于回复",
126224
+ stateOn: "开启",
126225
+ stateOff: "关闭"
126226
+ };
125873
126227
  var virtualMachineHostInput = {
125874
126228
  listLabel: "允许的主机",
125875
126229
  removeHost: "移除 {host}",
@@ -126056,6 +126410,7 @@ var zh = {
126056
126410
  advancedExternalMapping: advancedExternalMapping,
126057
126411
  advancedMemsearchConfig: advancedMemsearchConfig,
126058
126412
  advancedPlatformMembership: advancedPlatformMembership,
126413
+ advancedSeoDiscoverability: advancedSeoDiscoverability,
126059
126414
  advancedProviderConfig: advancedProviderConfig,
126060
126415
  advancedRecommendationSystemPrompts: advancedRecommendationSystemPrompts,
126061
126416
  advancedSmtp: advancedSmtp,
@@ -126330,6 +126685,7 @@ var zh = {
126330
126685
  analyticsLlmUsage: analyticsLlmUsage,
126331
126686
  analyticsTraces: analyticsTraces,
126332
126687
  profileLlmUsage: profileLlmUsage,
126688
+ profileOverviewTab: profileOverviewTab,
126333
126689
  virtualMachineHostInput: virtualMachineHostInput,
126334
126690
  virtualMachineAdminTab: virtualMachineAdminTab,
126335
126691
  virtualMachineNetworkPolicies: virtualMachineNetworkPolicies,
@@ -180454,7 +180810,7 @@ const Collapsible = Root$7;
180454
180810
  const CollapsibleTrigger = CollapsibleTrigger$1;
180455
180811
  const CollapsibleContent = CollapsibleContent$1;
180456
180812
 
180457
- const BAR_COLOR$1 = 'var(--color-amber-500, #f59e0b)';
180813
+ const BAR_COLOR$2 = 'var(--color-amber-500, #f59e0b)';
180458
180814
  const ERROR_MESSAGES = {
180459
180815
  forbidden: 'Completion breakdown is not available for this learner.',
180460
180816
  not_enrolled: 'This learner is not enrolled in this course.',
@@ -180471,7 +180827,7 @@ const formatPct = (value) => {
180471
180827
  };
180472
180828
  function CompletionBar({ value, label }) {
180473
180829
  const clamped = Math.min(Math.max(value, 0), 100);
180474
- return (jsx("span", { className: "block h-1.5 w-full rounded-full bg-gray-200", role: "progressbar", "aria-label": label, "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": clamped, children: jsx("span", { className: "block h-1.5 rounded-full", style: { width: `${clamped}%`, backgroundColor: BAR_COLOR$1 } }) }));
180830
+ return (jsx("span", { className: "block h-1.5 w-full rounded-full bg-gray-200", role: "progressbar", "aria-label": label, "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": clamped, children: jsx("span", { className: "block h-1.5 rounded-full", style: { width: `${clamped}%`, backgroundColor: BAR_COLOR$2 } }) }));
180475
180831
  }
180476
180832
  function SubsectionRow({ block }) {
180477
180833
  return (jsxs("li", { className: "space-y-1 py-2", children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxs("span", { className: "flex min-w-0 items-center gap-1.5 text-sm text-gray-700", children: [jsx("span", { className: "truncate", children: block.display_name }), block.special_exam_info ? (jsxs("span", { className: "inline-flex shrink-0 items-center gap-1 rounded-full bg-gray-100 px-2 py-0.5 text-[11px] text-gray-600", children: [jsx(Clock, { className: "h-3 w-3", "aria-hidden": "true" }), block.special_exam_info.short_description] })) : null] }), jsx("span", { className: "shrink-0 text-xs font-medium text-gray-600", children: formatPct(block.completion_percentage) })] }), jsx(CompletionBar, { value: block.completion_percentage, label: `${block.display_name} completion` })] }));
@@ -180517,7 +180873,7 @@ function CourseCompletionBreakdown({ username, courseId, tenantKey, skip = false
180517
180873
  }
180518
180874
 
180519
180875
  // Theme token (the same one bg-amber-500 resolves to), with Tailwind's default as fallback.
180520
- const COMPLETED_COLOR = 'var(--color-amber-500, #f59e0b)';
180876
+ const COMPLETED_COLOR$1 = 'var(--color-amber-500, #f59e0b)';
180521
180877
  const REMAINING_COLOR = '#E5E7EB';
180522
180878
  const formatDate$1 = (value) => {
180523
180879
  if (!value)
@@ -180621,7 +180977,7 @@ function EnrolledUserProgressModal({ open, onOpenChange, username, userName, ema
180621
180977
  ];
180622
180978
  const currentGradePct = fractionToPct((_f = (_e = item === null || item === void 0 ? void 0 : item.edx_progress) === null || _e === void 0 ? void 0 : _e.course_grade) === null || _f === void 0 ? void 0 : _f.percent);
180623
180979
  const passingPct = getPassingPct((_h = (_g = item === null || item === void 0 ? void 0 : item.edx_progress) === null || _g === void 0 ? void 0 : _g.grading_policy) === null || _h === void 0 ? void 0 : _h.grade_range);
180624
- return (jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: jsxs(DialogContent, { className: "max-w-2xl max-h-[85vh] overflow-y-auto", "aria-label": "Enrolled user progress", children: [jsxs(DialogHeader, { children: [jsx(DialogTitle, { children: userName || username || 'Learner progress' }), jsxs(DialogDescription, { children: [email ? `${email} · ` : '', resolvedName || (isProgram ? 'Program progress' : 'Course progress')] })] }), loading ? (jsx("div", { className: "flex items-center justify-center py-12", children: jsx("div", { className: "text-sm text-gray-500", children: "Loading..." }) })) : !item ? (jsx(EmptyStats, { title: "No progress data available" })) : (jsxs("div", { className: "space-y-6", children: [jsxs("div", { className: "relative mx-auto", style: { width: 220, height: 220 }, children: [jsx(ResponsiveContainer, { width: "100%", height: "100%", children: jsx(PieChart, { children: jsxs(Pie, { data: pieData, dataKey: "value", cx: "50%", cy: "50%", innerRadius: 75, outerRadius: 100, startAngle: 90, endAngle: -270, stroke: "none", isAnimationActive: false, children: [jsx(Cell, { fill: COMPLETED_COLOR }), jsx(Cell, { fill: REMAINING_COLOR })] }) }) }), jsxs("div", { className: "absolute inset-0 flex flex-col items-center justify-center pointer-events-none", children: [jsxs("span", { className: "text-3xl font-bold text-gray-700", children: [percentage, "%"] }), jsx("span", { className: "text-sm text-gray-500", children: "completed" })] })] }), jsxs("div", { className: "divide-y divide-[oklch(0.922_0_0)]", children: [jsx(DetailRow, { label: "Status", children: jsx("span", { className: `inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${((_j = item.completion) === null || _j === void 0 ? void 0 : _j.passed)
180980
+ return (jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: jsxs(DialogContent, { className: "max-w-2xl max-h-[85vh] overflow-y-auto", "aria-label": "Enrolled user progress", children: [jsxs(DialogHeader, { children: [jsx(DialogTitle, { children: userName || username || 'Learner progress' }), jsxs(DialogDescription, { children: [email ? `${email} · ` : '', resolvedName || (isProgram ? 'Program progress' : 'Course progress')] })] }), loading ? (jsx("div", { className: "flex items-center justify-center py-12", children: jsx("div", { className: "text-sm text-gray-500", children: "Loading..." }) })) : !item ? (jsx(EmptyStats, { title: "No progress data available" })) : (jsxs("div", { className: "space-y-6", children: [jsxs("div", { className: "relative mx-auto", style: { width: 220, height: 220 }, children: [jsx(ResponsiveContainer, { width: "100%", height: "100%", children: jsx(PieChart, { children: jsxs(Pie, { data: pieData, dataKey: "value", cx: "50%", cy: "50%", innerRadius: 75, outerRadius: 100, startAngle: 90, endAngle: -270, stroke: "none", isAnimationActive: false, children: [jsx(Cell, { fill: COMPLETED_COLOR$1 }), jsx(Cell, { fill: REMAINING_COLOR })] }) }) }), jsxs("div", { className: "absolute inset-0 flex flex-col items-center justify-center pointer-events-none", children: [jsxs("span", { className: "text-3xl font-bold text-gray-700", children: [percentage, "%"] }), jsx("span", { className: "text-sm text-gray-500", children: "completed" })] })] }), jsxs("div", { className: "divide-y divide-[oklch(0.922_0_0)]", children: [jsx(DetailRow, { label: "Status", children: jsx("span", { className: `inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${((_j = item.completion) === null || _j === void 0 ? void 0 : _j.passed)
180625
180981
  ? 'bg-green-50 text-green-700'
180626
180982
  : 'bg-gray-100 text-gray-600'}`, children: ((_k = item.completion) === null || _k === void 0 ? void 0 : _k.passed) ? 'Passed' : 'Not passed' }) }), jsx(DetailRow, { label: "Passed on", children: formatDate$1((_l = item.completion) === null || _l === void 0 ? void 0 : _l.passed_date) }), jsx(DetailRow, { label: "Time spent", children: item.time_spent || '—' }), jsx(DetailRow, { label: "Enrollment date", children: formatDate$1((_o = (_m = item.enrollment) === null || _m === void 0 ? void 0 : _m.started) !== null && _o !== void 0 ? _o : (_p = item.enrollment) === null || _p === void 0 ? void 0 : _p.created) })] }), !isProgram ? (jsx(CourseCompletionBreakdown, { username: username, courseId: normalizedId, tenantKey: tenantKey, skip: !open })) : null, ((_s = (_r = (_q = item.edx_progress) === null || _q === void 0 ? void 0 : _q.grading_policy) === null || _r === void 0 ? void 0 : _r.assignment_policies) === null || _s === void 0 ? void 0 : _s.length) ? (jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "rounded-lg border p-4", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx("h4", { className: "text-sm font-semibold text-gray-900", children: "Grades" }), jsx("p", { className: "text-xs text-gray-500", children: "This represents the weighted grade against the grade needed to pass this course." }), jsx(GradeBar, { currentPct: currentGradePct, passingPct: passingPct })] }), jsxs("div", { className: "flex items-start gap-2 rounded-md border border-amber-200 bg-amber-50 px-4 py-3", children: [jsx(TriangleAlert, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-600" }), jsxs("span", { className: "text-sm font-medium text-gray-800", children: ["A weighted grade of ", passingPct, "% is required to pass in this course"] })] }), jsxs("div", { className: "rounded-lg border p-4 space-y-3", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx("h4", { className: "text-sm font-semibold text-gray-900", children: "Grade summary" }), jsx("div", { className: "overflow-x-auto", children: jsxs("table", { className: "w-full border-collapse text-sm", children: [jsx("thead", { children: jsxs("tr", { className: "bg-amber-50 text-[11px] uppercase tracking-wide text-gray-600", children: [jsx("th", { className: "px-3 py-2 text-left font-medium", children: "Assignment type" }), jsx("th", { className: "px-3 py-2 text-right font-medium", children: "Weight" }), jsx("th", { className: "px-3 py-2 text-right font-medium", children: "Grade" }), jsx("th", { className: "px-3 py-2 text-right font-medium", children: "Weighted grade" })] }) }), jsxs("tbody", { children: [gradeSummary === null || gradeSummary === void 0 ? void 0 : gradeSummary.rows.map((row, index) => (jsxs("tr", { className: index % 2 === 0 ? '' : 'bg-gray-50', children: [jsxs("td", { className: "px-3 py-2 text-gray-800", children: [row.type, row.footnote ? (jsx("sup", { className: "ml-0.5 text-amber-500", children: row.footnote })) : null] }), jsxs("td", { className: "px-3 py-2 text-right text-gray-700", children: [row.weightPct, "%"] }), jsxs("td", { className: "px-3 py-2 text-right text-gray-700", children: [row.gradePct, "%"] }), jsxs("td", { className: "px-3 py-2 text-right font-semibold text-amber-600", children: [row.weightedGradePct, "%"] })] }, row.type))), jsxs("tr", { className: "border-l-2 border-amber-400 bg-amber-50", children: [jsx("td", { className: "px-3 py-2 font-medium text-gray-800", colSpan: 3, children: "Current weighted grade summary" }), jsxs("td", { className: "px-3 py-2 text-right font-bold text-amber-600", children: [currentGradePct, "%"] })] })] })] }) }), gradeSummary && gradeSummary.footnotes.length > 0 ? (jsx("div", { className: "space-y-1", children: gradeSummary.footnotes.map((note, index) => (jsxs("p", { className: "text-xs text-gray-500", children: [jsx("sup", { className: "text-amber-500", children: index + 1 }), " ", note] }, note))) })) : null] })] })) : null] }))] }) }));
180627
180983
  }
@@ -180822,10 +181178,10 @@ function GradebookCard({ row, icon: Icon, onClick, }) {
180822
181178
  }
180823
181179
  : undefined, "aria-label": clickable ? t('gradebookGradebookTab.viewProgressAriaLabel', { name: row.name }) : undefined, children: jsx(CardContent, { className: "p-4", children: jsxs("div", { className: "flex items-start justify-between gap-3", children: [jsxs("div", { className: "flex items-start gap-3 min-w-0", children: [jsx("div", { className: "flex-shrink-0 w-10 h-10 bg-gradient-to-br from-blue-500 to-blue-600 rounded-lg flex items-center justify-center", children: jsx(Icon, { className: "h-5 w-5 text-white", "aria-hidden": "true" }) }), jsxs("div", { className: "min-w-0", children: [jsx("h4", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100 truncate", children: row.name }), row.subtitle && (jsxs("div", { className: "flex items-center gap-1.5 mt-1 text-xs text-gray-400", children: [jsx(Calendar$1, { className: "h-3 w-3" }), row.subtitle] })), row.id && (jsxs("div", { className: "flex items-center gap-1 mt-1 text-xs text-gray-400", children: [jsxs("span", { className: "flex-shrink-0", children: [t('gradebookGradebookTab.idLabel'), ":"] }), jsx("span", { onClick: (e) => e.stopPropagation(), onMouseDown: (e) => e.stopPropagation(), className: "min-w-0 truncate font-mono select-all cursor-text", title: row.id, children: row.id })] }))] })] }), row.badgeLabel && (jsx(Badge, { className: cn('flex-shrink-0', BADGE_TONE[(_a = row.badgeTone) !== null && _a !== void 0 ? _a : 'neutral']), children: row.badgeLabel }))] }) }) }));
180824
181180
  }
180825
- function GradebookList({ org, username, types }) {
181181
+ function GradebookList({ org, username, types, initialType }) {
180826
181182
  var _a, _b, _c;
180827
181183
  const t = useT();
180828
- const [type, setType] = useState(types[0]);
181184
+ const [type, setType] = useState(initialType && types.includes(initialType) ? initialType : types[0]);
180829
181185
  const [searchQuery, setSearchQuery] = useState('');
180830
181186
  const [page, setPage] = useState(1);
180831
181187
  const [selected, setSelected] = useState(null);
@@ -180845,8 +181201,8 @@ function GradebookList({ org, username, types }) {
180845
181201
  setSelected(null);
180846
181202
  }, username: username, email: selected === null || selected === void 0 ? void 0 : selected.email, contentId: (_b = selected === null || selected === void 0 ? void 0 : selected.contentId) !== null && _b !== void 0 ? _b : '', contentName: selected === null || selected === void 0 ? void 0 : selected.contentName, metric: (_c = selected === null || selected === void 0 ? void 0 : selected.metric) !== null && _c !== void 0 ? _c : 'course', tenantKey: org })] }));
180847
181203
  }
180848
- function GradebookTab({ org, username }) {
180849
- return jsx(GradebookList, { org: org, username: username, types: GRADEBOOK_TYPES });
181204
+ function GradebookTab({ org, username, initialType }) {
181205
+ return (jsx(GradebookList, { org: org, username: username, types: GRADEBOOK_TYPES, initialType: initialType }));
180850
181206
  }
180851
181207
  const CREDENTIALS_TYPES = ['credentials'];
180852
181208
  const SKILLS_TYPES = ['skills'];
@@ -272347,6 +272703,18 @@ const CHART_SERIES_COLORS = [
272347
272703
  '#e87ba4', // magenta
272348
272704
  '#008300', // green
272349
272705
  ];
272706
+ /**
272707
+ * Ordinal blue ramp for ordered measures (latency p50→p99). One hue,
272708
+ * light→dark — never a rainbow for an ordered scale. The lightest step clears
272709
+ * 2:1 against white.
272710
+ */
272711
+ const CHART_ORDINAL_RAMP = [
272712
+ '#86b6ef', // p50
272713
+ '#5598e7', // p75
272714
+ '#2a78d6', // p90
272715
+ '#1c5cab', // p95
272716
+ '#104281', // p99
272717
+ ];
272350
272718
  /**
272351
272719
  * Color follows the entity: a service keeps its hue whether or not the other
272352
272720
  * services are on screen. Services beyond this list fold into slots in first-
@@ -272533,7 +272901,7 @@ function sharePercent(value, total) {
272533
272901
  }
272534
272902
 
272535
272903
  /** Single series, so the palette's lead hue; it clears 3:1 on white. */
272536
- const BAR_COLOR = CHART_SERIES_COLORS[0];
272904
+ const BAR_COLOR$1 = CHART_SERIES_COLORS[0];
272537
272905
  const PLOT_HEIGHT = 176;
272538
272906
  const MAX_X_LABELS = 5;
272539
272907
  /**
@@ -272582,7 +272950,7 @@ function SpendChart({ points, granularity, }) {
272582
272950
  // The whole column slot is the hover target, not just the bar.
272583
272951
  className: "flex h-full min-w-0 flex-1 items-end justify-center", onMouseEnter: () => setActive(index), children: jsx("div", { className: "w-full max-w-[24px] rounded-t-[4px] transition-opacity", style: {
272584
272952
  height: point.totalCost > 0 ? `max(${height}%, 2px)` : 0,
272585
- background: BAR_COLOR,
272953
+ background: BAR_COLOR$1,
272586
272954
  opacity: active === null || isActive ? 1 : 0.45,
272587
272955
  } }) }, point.date));
272588
272956
  }) })] }), jsx("div", { className: "relative mt-2 h-4 text-[11px] text-gray-500 dark:text-gray-400", "aria-hidden": "true", children: points.map((point, index) => labelIndexes.has(index) ? (jsx("span", { className: "absolute whitespace-nowrap", style: index === 0
@@ -272595,6 +272963,20 @@ function SpendChart({ points, granularity, }) {
272595
272963
  }, children: formatBucket(point.date, granularity) }, point.date)) : null) })] })] }), jsxs("table", { className: "sr-only", children: [jsx("caption", { children: t('profileLlmUsage.chartTableCaption') }), jsx("thead", { children: jsxs("tr", { children: [jsx("th", { scope: "col", children: t('profileLlmUsage.colPeriod') }), jsx("th", { scope: "col", children: t('profileLlmUsage.colCost') })] }) }), jsx("tbody", { children: points.map((point) => (jsxs("tr", { children: [jsx("td", { children: formatBucket(point.date, granularity) }), jsx("td", { children: formatCost(point.totalCost) })] }, point.date))) })] })] }));
272596
272964
  }
272597
272965
 
272966
+ /**
272967
+ * Cost share per row as a labelled bar list — the Usage tab's "By model" and
272968
+ * "By service" cards, also reused by the profile Overview.
272969
+ */
272970
+ function RankedBars({ rows, total, colorFor, }) {
272971
+ return (jsx("ul", { className: "flex flex-col gap-3", children: rows.map((row) => {
272972
+ const share = sharePercent(row.totalCost, total);
272973
+ return (jsxs("li", { className: "flex flex-col gap-1.5", children: [jsxs("div", { className: "flex items-baseline justify-between gap-3 text-[13px]", children: [jsxs("span", { className: "flex min-w-0 items-center gap-2 font-medium text-gray-900 dark:text-gray-100", children: [jsx("span", { className: "h-2 w-2 flex-shrink-0 rounded-[2px]", style: { background: colorFor(row) }, "aria-hidden": "true" }), jsx("span", { className: "truncate", title: row.label, children: row.label })] }), jsxs("span", { className: "whitespace-nowrap tabular-nums text-gray-700 dark:text-gray-300", children: [formatCost(row.totalCost), jsxs("span", { className: "text-gray-500 dark:text-gray-400", children: [" \u00B7 ", share, "%"] })] })] }), jsx("div", { className: "h-1.5 overflow-hidden rounded-full bg-gray-100 dark:bg-gray-800", "aria-hidden": "true", children: jsx("div", { className: "h-full rounded-full", style: { width: `${Math.min(100, share)}%`, background: colorFor(row) } }) })] }, row.key));
272974
+ }) }));
272975
+ }
272976
+ function BreakdownSkeleton() {
272977
+ return (jsx("div", { className: "flex flex-col gap-4", children: [0, 1, 2, 3].map((i) => (jsxs("div", { className: "flex flex-col gap-2", children: [jsx(Skeleton, { className: "h-4 w-3/4" }), jsx(Skeleton, { className: "h-1.5 w-full" })] }, i))) }));
272978
+ }
272979
+
272598
272980
  const RANGE_LABEL_KEYS = {
272599
272981
  today: 'rangeToday',
272600
272982
  '7d': 'range7d',
@@ -272614,11 +272996,11 @@ const CHART_SUBTITLE_KEYS = {
272614
272996
  week: 'chartSubtitleWeek',
272615
272997
  month: 'chartSubtitleMonth',
272616
272998
  };
272617
- const BREAKDOWN_ROWS = 5;
272999
+ const BREAKDOWN_ROWS$1 = 5;
272618
273000
  const MODEL_BAR_COLOR = CHART_SERIES_COLORS[0];
272619
- const CARD = 'rounded-xl border border-gray-200 bg-white dark:border-gray-800 dark:bg-gray-950';
273001
+ const CARD$1 = 'rounded-xl border border-gray-200 bg-white dark:border-gray-800 dark:bg-gray-950';
272620
273002
  function Card({ title, subtitle, aside, children, className, bodyClassName, }) {
272621
- return (jsxs("section", { className: cn(CARD, className), "aria-label": title, children: [jsxs("div", { className: "flex items-start justify-between gap-4 px-5 pt-5", children: [jsxs("div", { className: "min-w-0", children: [jsx("h4", { className: "text-[15px] font-semibold text-gray-900 dark:text-gray-100", children: title }), subtitle && (jsx("p", { className: "mt-0.5 text-[13px] text-gray-500 dark:text-gray-400", children: subtitle }))] }), aside] }), jsx("div", { className: cn('px-5 pb-5 pt-4', bodyClassName), children: children })] }));
273003
+ return (jsxs("section", { className: cn(CARD$1, className), "aria-label": title, children: [jsxs("div", { className: "flex items-start justify-between gap-4 px-5 pt-5", children: [jsxs("div", { className: "min-w-0", children: [jsx("h4", { className: "text-[15px] font-semibold text-gray-900 dark:text-gray-100", children: title }), subtitle && (jsx("p", { className: "mt-0.5 text-[13px] text-gray-500 dark:text-gray-400", children: subtitle }))] }), aside] }), jsx("div", { className: cn('px-5 pb-5 pt-4', bodyClassName), children: children })] }));
272622
273004
  }
272623
273005
  function RangeControl({ value, onChange, }) {
272624
273006
  const t = useT();
@@ -272644,23 +273026,14 @@ function RangeControl({ value, onChange, }) {
272644
273026
  : 'font-medium text-gray-600 hover:text-gray-900 dark:text-gray-300'), children: t(`profileLlmUsage.${RANGE_LABEL_KEYS[range]}`) }, range));
272645
273027
  }) }));
272646
273028
  }
272647
- function StatTile({ label, value, sub, loading, }) {
272648
- return (jsxs("div", { className: cn(CARD, 'flex flex-col gap-2 p-4'), children: [jsx("p", { className: "text-[13px] font-medium text-gray-500 dark:text-gray-400", children: label }), loading ? (jsxs(Fragment$1, { children: [jsx(Skeleton, { className: "h-7 w-24" }), jsx(Skeleton, { className: "h-4 w-20" })] })) : (jsxs(Fragment$1, { children: [jsx("p", { className: "text-[26px] font-semibold leading-tight tracking-tight text-gray-900 dark:text-gray-100", children: value }), jsx("p", { className: "min-h-[1rem] text-xs text-gray-500 tabular-nums dark:text-gray-400", children: sub })] }))] }));
273029
+ function StatTile$1({ label, value, sub, loading, }) {
273030
+ return (jsxs("div", { className: cn(CARD$1, 'flex flex-col gap-2 p-4'), children: [jsx("p", { className: "text-[13px] font-medium text-gray-500 dark:text-gray-400", children: label }), loading ? (jsxs(Fragment$1, { children: [jsx(Skeleton, { className: "h-7 w-24" }), jsx(Skeleton, { className: "h-4 w-20" })] })) : (jsxs(Fragment$1, { children: [jsx("p", { className: "text-[26px] font-semibold leading-tight tracking-tight text-gray-900 dark:text-gray-100", children: value }), jsx("p", { className: "min-h-[1rem] text-xs text-gray-500 tabular-nums dark:text-gray-400", children: sub })] }))] }));
272649
273031
  }
272650
273032
  function StateMessage({ icon, tone = 'neutral', title, body, action, }) {
272651
- return (jsxs("div", { className: cn(CARD, 'flex flex-col items-center gap-3 px-6 py-14 text-center'), role: tone === 'error' ? 'alert' : undefined, children: [jsx("div", { className: cn('flex h-12 w-12 items-center justify-center rounded-xl', tone === 'error'
273033
+ return (jsxs("div", { className: cn(CARD$1, 'flex flex-col items-center gap-3 px-6 py-14 text-center'), role: tone === 'error' ? 'alert' : undefined, children: [jsx("div", { className: cn('flex h-12 w-12 items-center justify-center rounded-xl', tone === 'error'
272652
273034
  ? 'bg-red-50 text-red-700 dark:bg-red-950 dark:text-red-300'
272653
273035
  : 'bg-gray-100 text-gray-500 dark:bg-gray-800 dark:text-gray-400'), "aria-hidden": "true", children: icon }), jsx("h4", { className: "text-base font-semibold text-gray-900 dark:text-gray-100", children: title }), jsx("p", { className: "max-w-sm text-sm leading-relaxed text-gray-500 dark:text-gray-400", children: body }), action] }));
272654
273036
  }
272655
- function RankedBars({ rows, total, colorFor, }) {
272656
- return (jsx("ul", { className: "flex flex-col gap-3", children: rows.map((row) => {
272657
- const share = sharePercent(row.totalCost, total);
272658
- return (jsxs("li", { className: "flex flex-col gap-1.5", children: [jsxs("div", { className: "flex items-baseline justify-between gap-3 text-[13px]", children: [jsxs("span", { className: "flex min-w-0 items-center gap-2 font-medium text-gray-900 dark:text-gray-100", children: [jsx("span", { className: "h-2 w-2 flex-shrink-0 rounded-[2px]", style: { background: colorFor(row) }, "aria-hidden": "true" }), jsx("span", { className: "truncate", title: row.label, children: row.label })] }), jsxs("span", { className: "whitespace-nowrap tabular-nums text-gray-700 dark:text-gray-300", children: [formatCost(row.totalCost), jsxs("span", { className: "text-gray-500 dark:text-gray-400", children: [" \u00B7 ", share, "%"] })] })] }), jsx("div", { className: "h-1.5 overflow-hidden rounded-full bg-gray-100 dark:bg-gray-800", "aria-hidden": "true", children: jsx("div", { className: "h-full rounded-full", style: { width: `${Math.min(100, share)}%`, background: colorFor(row) } }) })] }, row.key));
272659
- }) }));
272660
- }
272661
- function BreakdownSkeleton() {
272662
- return (jsx("div", { className: "flex flex-col gap-4", children: [0, 1, 2, 3].map((i) => (jsxs("div", { className: "flex flex-col gap-2", children: [jsx(Skeleton, { className: "h-4 w-3/4" }), jsx(Skeleton, { className: "h-1.5 w-full" })] }, i))) }));
272663
- }
272664
273037
  function SectionError() {
272665
273038
  const t = useT();
272666
273039
  return (jsxs("p", { className: "flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400", children: [jsx(CircleAlert, { className: "h-4 w-4 text-red-600", "aria-hidden": "true" }), t('profileLlmUsage.sectionError')] }));
@@ -272707,7 +273080,6 @@ function LlmUsageTab({ org, username, isOwnProfile = true }) {
272707
273080
  const summary = useUserLlmUsageSummary(scope);
272708
273081
  const spend = useUserLlmSpendOverTime({ ...scope, granularity });
272709
273082
  const byModel = useUserLlmCostByModel({ ...scope, limit: 20 });
272710
- const byService = useUserLlmCostByService(scope);
272711
273083
  const activity = useUserLlmRecentActivity({
272712
273084
  ...scope,
272713
273085
  page,
@@ -272723,7 +273095,6 @@ function LlmUsageTab({ org, username, isOwnProfile = true }) {
272723
273095
  summary.refetch();
272724
273096
  spend.refetch();
272725
273097
  byModel.refetch();
272726
- byService.refetch();
272727
273098
  activity.refetch();
272728
273099
  if (openTraceId)
272729
273100
  steps.refetch();
@@ -272734,15 +273105,8 @@ function LlmUsageTab({ org, username, isOwnProfile = true }) {
272734
273105
  label: row.model || t('profileLlmUsage.unknownModel'),
272735
273106
  totalCost: row.totalCost,
272736
273107
  count: row.count,
272737
- })), BREAKDOWN_ROWS, t('profileLlmUsage.otherRow')), [byModel.models, t]);
272738
- const serviceRows = useMemo(() => foldTail(byService.services.map((row, index) => ({
272739
- key: row.service || `unknown-${index}`,
272740
- label: row.service || t('profileLlmUsage.unknownService'),
272741
- totalCost: row.totalCost,
272742
- count: row.count,
272743
- })), BREAKDOWN_ROWS, t('profileLlmUsage.otherRow')), [byService.services, t]);
273108
+ })), BREAKDOWN_ROWS$1, t('profileLlmUsage.otherRow')), [byModel.models, t]);
272744
273109
  const modelTotal = modelRows.reduce((sum, row) => sum + row.totalCost, 0);
272745
- const serviceTotal = serviceRows.reduce((sum, row) => sum + row.totalCost, 0);
272746
273110
  const totals = summary.summary;
272747
273111
  const periodLabel = t(`profileLlmUsage.${PERIOD_LABEL_KEYS[range]}`);
272748
273112
  const next = widerRange(range);
@@ -272787,15 +273151,13 @@ function LlmUsageTab({ org, username, isOwnProfile = true }) {
272787
273151
  }
272788
273152
  else {
272789
273153
  const loadingTotals = summary.isLoading || summary.isIdle;
272790
- body = (jsxs(Fragment$1, { children: [jsxs("div", { className: "grid grid-cols-2 gap-3 xl:grid-cols-4", children: [jsx(StatTile, { label: t('profileLlmUsage.kpiSpend'), value: formatCost(totals === null || totals === void 0 ? void 0 : totals.totalCost), sub: periodLabel, loading: loadingTotals }), jsx(StatTile, { label: t('profileLlmUsage.kpiTokens'), value: formatCompact(totals === null || totals === void 0 ? void 0 : totals.totalTokens), sub: totals && totals.count > 0
273154
+ body = (jsxs(Fragment$1, { children: [jsxs("div", { className: "grid grid-cols-2 gap-3 xl:grid-cols-4", children: [jsx(StatTile$1, { label: t('profileLlmUsage.kpiSpend'), value: formatCost(totals === null || totals === void 0 ? void 0 : totals.totalCost), sub: periodLabel, loading: loadingTotals }), jsx(StatTile$1, { label: t('profileLlmUsage.kpiTokens'), value: formatCompact(totals === null || totals === void 0 ? void 0 : totals.totalTokens), sub: totals && totals.count > 0
272791
273155
  ? t('profileLlmUsage.kpiTokensSub', {
272792
273156
  value: formatCompact(totals.totalTokens / totals.count),
272793
273157
  })
272794
- : undefined, loading: loadingTotals }), jsx(StatTile, { label: t('profileLlmUsage.kpiRequests'), value: formatInteger(totals === null || totals === void 0 ? void 0 : totals.count), sub: t('profileLlmUsage.kpiRequestsSub'), loading: loadingTotals }), jsx(StatTile, { label: t('profileLlmUsage.kpiAvgCost'), value: totals && totals.count > 0
273158
+ : undefined, loading: loadingTotals }), jsx(StatTile$1, { label: t('profileLlmUsage.kpiRequests'), value: formatInteger(totals === null || totals === void 0 ? void 0 : totals.count), sub: t('profileLlmUsage.kpiRequestsSub'), loading: loadingTotals }), jsx(StatTile$1, { label: t('profileLlmUsage.kpiAvgCost'), value: totals && totals.count > 0
272795
273159
  ? formatCost(totals.totalCost / totals.count, { precise: true })
272796
- : '—', sub: t('profileLlmUsage.kpiAvgCostSub'), loading: loadingTotals })] }), jsx(Card, { title: t('profileLlmUsage.chartTitle'), subtitle: t(`profileLlmUsage.${CHART_SUBTITLE_KEYS[granularity]}`), aside: totals && (jsx("span", { className: "text-[15px] font-semibold tabular-nums text-gray-900 dark:text-gray-100", children: formatCost(totals.totalCost) })), bodyClassName: "pt-2", children: spend.isLoading || spend.isIdle ? (jsx(Skeleton, { className: "h-[220px] w-full" })) : spend.error ? (jsx(SectionError, {})) : series.length === 0 ? (jsx("p", { className: "py-10 text-center text-sm text-gray-500 dark:text-gray-400", children: t('profileLlmUsage.chartNoData') })) : (jsx(SpendChart, { points: series, granularity: granularity })) }), jsxs("div", { className: "grid grid-cols-1 gap-3 md:grid-cols-2", children: [jsx(Card, { title: t('profileLlmUsage.byModelTitle'), subtitle: t('profileLlmUsage.byModelSubtitle'), children: byModel.isLoading || byModel.isIdle ? (jsx(BreakdownSkeleton, {})) : byModel.error ? (jsx(SectionError, {})) : modelRows.length === 0 ? (jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: t('profileLlmUsage.breakdownEmpty') })) : (jsx(RankedBars, { rows: modelRows, total: modelTotal, colorFor: () => MODEL_BAR_COLOR })) }), jsx(Card, { title: t('profileLlmUsage.byServiceTitle'), subtitle: t('profileLlmUsage.byServiceSubtitle'), children: byService.isLoading || byService.isIdle ? (jsx(BreakdownSkeleton, {})) : byService.error ? (jsx(SectionError, {})) : serviceRows.length === 0 ? (jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: t('profileLlmUsage.breakdownEmpty') })) : (jsx(RankedBars, { rows: serviceRows, total: serviceTotal,
272797
- // Colour follows the service, so "chat" is the same hue everywhere.
272798
- colorFor: (row) => (row.isOther ? '#9ca3af' : colorForSeries(row.key)) })) })] }), jsxs("section", { className: cn(CARD, 'overflow-hidden'), "aria-labelledby": "llm-activity-heading", children: [jsxs("div", { className: "border-b border-gray-200 px-5 py-4 dark:border-gray-800", children: [jsx("h4", { id: "llm-activity-heading", className: "text-[15px] font-semibold text-gray-900 dark:text-gray-100", children: t('profileLlmUsage.activityTitle') }), jsx("p", { className: "mt-0.5 text-[13px] text-gray-500 dark:text-gray-400", children: t('profileLlmUsage.activitySubtitle') })] }), activity.isLoading || activity.isIdle ? (jsx("div", { className: "flex flex-col gap-3 p-5", children: [0, 1, 2, 3].map((i) => (jsx(Skeleton, { className: "h-8 w-full" }, i))) })) : activity.error ? (jsx("div", { className: "p-5", children: jsx(SectionError, {}) })) : activity.isEmpty || activity.rows.length === 0 ? (jsx("p", { className: "p-5 text-sm text-gray-500 dark:text-gray-400", children: t('profileLlmUsage.activityEmpty') })) : (jsxs(Fragment$1, { children: [jsx("div", { className: "overflow-x-auto", children: jsxs("table", { className: "w-full text-[13px]", children: [jsx("thead", { children: jsxs("tr", { className: "bg-gray-50 text-left text-gray-500 dark:bg-gray-900 dark:text-gray-400", children: [jsx("th", { scope: "col", className: "px-5 py-2.5 font-medium", children: t('profileLlmUsage.colWhen') }), jsx("th", { scope: "col", className: "px-3 py-2.5 font-medium", children: t('profileLlmUsage.colService') }), jsx("th", { scope: "col", className: "hidden px-3 py-2.5 font-medium md:table-cell", children: t('profileLlmUsage.colSession') }), jsx("th", { scope: "col", className: "px-3 py-2.5 text-right font-medium", children: t('profileLlmUsage.colLatency') }), jsx("th", { scope: "col", className: "px-3 py-2.5 text-right font-medium", children: t('profileLlmUsage.colCost') }), jsx("th", { scope: "col", className: "w-12 py-2.5 pl-2 pr-5", children: jsx("span", { className: "sr-only", children: t('profileLlmUsage.colDetails') }) })] }) }), jsx("tbody", { children: activity.rows.map((trace) => {
273160
+ : '—', sub: t('profileLlmUsage.kpiAvgCostSub'), loading: loadingTotals })] }), jsx(Card, { title: t('profileLlmUsage.chartTitle'), subtitle: t(`profileLlmUsage.${CHART_SUBTITLE_KEYS[granularity]}`), aside: totals && (jsx("span", { className: "text-[15px] font-semibold tabular-nums text-gray-900 dark:text-gray-100", children: formatCost(totals.totalCost) })), bodyClassName: "pt-2", children: spend.isLoading || spend.isIdle ? (jsx(Skeleton, { className: "h-[220px] w-full" })) : spend.error ? (jsx(SectionError, {})) : series.length === 0 ? (jsx("p", { className: "py-10 text-center text-sm text-gray-500 dark:text-gray-400", children: t('profileLlmUsage.chartNoData') })) : (jsx(SpendChart, { points: series, granularity: granularity })) }), jsx(Card, { title: t('profileLlmUsage.byModelTitle'), subtitle: t('profileLlmUsage.byModelSubtitle'), children: byModel.isLoading || byModel.isIdle ? (jsx(BreakdownSkeleton, {})) : byModel.error ? (jsx(SectionError, {})) : modelRows.length === 0 ? (jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: t('profileLlmUsage.breakdownEmpty') })) : (jsx(RankedBars, { rows: modelRows, total: modelTotal, colorFor: () => MODEL_BAR_COLOR })) }), jsxs("section", { className: cn(CARD$1, 'overflow-hidden'), "aria-labelledby": "llm-activity-heading", children: [jsxs("div", { className: "border-b border-gray-200 px-5 py-4 dark:border-gray-800", children: [jsx("h4", { id: "llm-activity-heading", className: "text-[15px] font-semibold text-gray-900 dark:text-gray-100", children: t('profileLlmUsage.activityTitle') }), jsx("p", { className: "mt-0.5 text-[13px] text-gray-500 dark:text-gray-400", children: t('profileLlmUsage.activitySubtitle') })] }), activity.isLoading || activity.isIdle ? (jsx("div", { className: "flex flex-col gap-3 p-5", children: [0, 1, 2, 3].map((i) => (jsx(Skeleton, { className: "h-8 w-full" }, i))) })) : activity.error ? (jsx("div", { className: "p-5", children: jsx(SectionError, {}) })) : activity.isEmpty || activity.rows.length === 0 ? (jsx("p", { className: "p-5 text-sm text-gray-500 dark:text-gray-400", children: t('profileLlmUsage.activityEmpty') })) : (jsxs(Fragment$1, { children: [jsx("div", { className: "overflow-x-auto", children: jsxs("table", { className: "w-full text-[13px]", children: [jsx("thead", { children: jsxs("tr", { className: "bg-gray-50 text-left text-gray-500 dark:bg-gray-900 dark:text-gray-400", children: [jsx("th", { scope: "col", className: "px-5 py-2.5 font-medium", children: t('profileLlmUsage.colWhen') }), jsx("th", { scope: "col", className: "px-3 py-2.5 font-medium", children: t('profileLlmUsage.colService') }), jsx("th", { scope: "col", className: "hidden px-3 py-2.5 font-medium md:table-cell", children: t('profileLlmUsage.colSession') }), jsx("th", { scope: "col", className: "px-3 py-2.5 text-right font-medium", children: t('profileLlmUsage.colLatency') }), jsx("th", { scope: "col", className: "px-3 py-2.5 text-right font-medium", children: t('profileLlmUsage.colCost') }), jsx("th", { scope: "col", className: "w-12 py-2.5 pl-2 pr-5", children: jsx("span", { className: "sr-only", children: t('profileLlmUsage.colDetails') }) })] }) }), jsx("tbody", { children: activity.rows.map((trace) => {
272799
273161
  const open = trace.id === openTraceId;
272800
273162
  const when = formatWhen(trace.timestamp);
272801
273163
  const service = trace.name || t('profileLlmUsage.unknownService');
@@ -272817,16 +273179,602 @@ function LlmUsageTab({ org, username, isOwnProfile = true }) {
272817
273179
  setPage((current) => current + 1);
272818
273180
  }, children: [t('profileLlmUsage.next'), jsx(ChevronRight, { className: "h-4 w-4", "aria-hidden": "true" })] })] })] }))] }))] })] }));
272819
273181
  }
272820
- const isRefreshing = summary.isFetching ||
272821
- spend.isFetching ||
272822
- byModel.isFetching ||
272823
- byService.isFetching ||
272824
- activity.isFetching;
273182
+ const isRefreshing = summary.isFetching || spend.isFetching || byModel.isFetching || activity.isFetching;
272825
273183
  return (jsxs("div", { className: "flex flex-col gap-5", "data-testid": "llm-usage-tab", children: [jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [jsx(RangeControl, { value: range, onChange: changeRange }), jsxs("div", { className: "flex items-center gap-3", children: [jsxs("span", { className: "inline-flex items-center gap-1.5 text-[13px] text-gray-500 dark:text-gray-400", children: [jsx(Lock, { className: "h-3.5 w-3.5", "aria-hidden": "true" }), isOwnProfile
272826
273184
  ? t('profileLlmUsage.scopeSelf')
272827
273185
  : t('profileLlmUsage.scopeUser', { username })] }), jsx(Button$1, { variant: "outline", size: "icon", className: "h-9 w-9", onClick: refreshAll, disabled: isRefreshing, "aria-label": t('profileLlmUsage.refresh'), title: t('profileLlmUsage.refresh'), children: jsx(RefreshCw, { className: cn('h-4 w-4', isRefreshing && 'animate-spin'), "aria-hidden": "true" }) })] })] }), body] }));
272828
273186
  }
272829
273187
 
273188
+ /** How many of each list the overview shows before pointing at the full tab. */
273189
+ const OVERVIEW_COURSE_LIMIT = 5;
273190
+ const OVERVIEW_CONVERSATION_LIMIT = 5;
273191
+ const OVERVIEW_MEMORY_LIMIT = 3;
273192
+ /** A course's completion as a whole percent clamped to 0–100. */
273193
+ function courseProgressPercent(course) {
273194
+ var _a;
273195
+ const raw = (_a = course.completion) === null || _a === void 0 ? void 0 : _a.completion_percentage;
273196
+ if (raw === undefined || raw === null || !Number.isFinite(raw))
273197
+ return 0;
273198
+ return Math.min(100, Math.max(0, Math.round(raw)));
273199
+ }
273200
+ /**
273201
+ * Done with a course: every block complete, or the course passed on grade —
273202
+ * a learner can pass without opening every page, and that still counts.
273203
+ */
273204
+ function isCourseCompleted(course) {
273205
+ const completion = course.completion;
273206
+ if (!completion)
273207
+ return false;
273208
+ return completion.completed || completion.passed || courseProgressPercent(course) >= 100;
273209
+ }
273210
+ function summarizeLearning(courses) {
273211
+ let completed = 0;
273212
+ let inProgress = 0;
273213
+ let sum = 0;
273214
+ for (const course of courses) {
273215
+ const percent = courseProgressPercent(course);
273216
+ sum += percent;
273217
+ if (isCourseCompleted(course))
273218
+ completed += 1;
273219
+ else if (percent > 0)
273220
+ inProgress += 1;
273221
+ }
273222
+ const total = courses.length;
273223
+ return {
273224
+ total,
273225
+ completed,
273226
+ inProgress,
273227
+ notStarted: total - completed - inProgress,
273228
+ averageProgress: total ? Math.round(sum / total) : 0,
273229
+ };
273230
+ }
273231
+ const timeOf = (value) => {
273232
+ if (!value)
273233
+ return Number.NaN;
273234
+ return new Date(value).getTime();
273235
+ };
273236
+ /** Most recently enrolled first; courses without a usable date sink to the end. */
273237
+ function sortCoursesByRecency(courses) {
273238
+ return [...courses].sort((a, b) => {
273239
+ var _a, _b;
273240
+ const left = timeOf((_a = a.enrollment) === null || _a === void 0 ? void 0 : _a.created);
273241
+ const right = timeOf((_b = b.enrollment) === null || _b === void 0 ? void 0 : _b.created);
273242
+ if (Number.isNaN(left) && Number.isNaN(right))
273243
+ return 0;
273244
+ if (Number.isNaN(left))
273245
+ return 1;
273246
+ if (Number.isNaN(right))
273247
+ return -1;
273248
+ return right - left;
273249
+ });
273250
+ }
273251
+ /**
273252
+ * Furthest along first: completed courses, then in-progress ones by percent,
273253
+ * then those not started — most recent enrollment first within a tie.
273254
+ */
273255
+ function sortCoursesByProgress(courses) {
273256
+ const stage = (course) => isCourseCompleted(course) ? 2 : courseProgressPercent(course) > 0 ? 1 : 0;
273257
+ const byRecency = sortCoursesByRecency(courses);
273258
+ return byRecency.sort((a, b) => {
273259
+ const stageDiff = stage(b) - stage(a);
273260
+ if (stageDiff)
273261
+ return stageDiff;
273262
+ return courseProgressPercent(b) - courseProgressPercent(a);
273263
+ });
273264
+ }
273265
+ /** Seconds as `2h 15m`, `45m`, `<1m`; a missing value is a dash. */
273266
+ function formatDuration(seconds) {
273267
+ if (seconds === null || seconds === undefined || !Number.isFinite(seconds) || seconds < 0) {
273268
+ return '—';
273269
+ }
273270
+ if (seconds === 0)
273271
+ return '0m';
273272
+ if (seconds < 60)
273273
+ return '<1m';
273274
+ const minutes = Math.round(seconds / 60);
273275
+ if (minutes < 60)
273276
+ return `${minutes}m`;
273277
+ const hours = Math.floor(minutes / 60);
273278
+ const rest = minutes % 60;
273279
+ return rest ? `${hours}h ${rest}m` : `${hours}h`;
273280
+ }
273281
+ /** `3 days ago`; empty for a missing or unparseable timestamp. */
273282
+ function formatRelative(iso) {
273283
+ if (!iso)
273284
+ return '';
273285
+ const date = new Date(iso);
273286
+ if (Number.isNaN(date.getTime()))
273287
+ return '';
273288
+ return formatDistanceToNow(date, { addSuffix: true });
273289
+ }
273290
+ function formatShortDate(iso) {
273291
+ if (!iso)
273292
+ return '—';
273293
+ const date = new Date(iso);
273294
+ if (Number.isNaN(date.getTime()))
273295
+ return '—';
273296
+ return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
273297
+ }
273298
+ /** Whole-percent share, guarding an empty denominator. */
273299
+ function percentOf(part, whole) {
273300
+ if (!whole || whole <= 0)
273301
+ return 0;
273302
+ return Math.round((part / whole) * 100);
273303
+ }
273304
+
273305
+ /** The AI figures on the overview are always the last 30 days. */
273306
+ const OVERVIEW_LLM_RANGE = '30d';
273307
+ /** Enough enrollments to count active ones without paging. */
273308
+ const OVERVIEW_ENROLLMENT_PAGE_SIZE = 50;
273309
+ /** Models fetched for the breakdown; the tab folds the tail into "Other". */
273310
+ const OVERVIEW_MODEL_LIMIT = 10;
273311
+ const statusOf = (error) => error && typeof error === 'object' ? error.status : undefined;
273312
+ /**
273313
+ * Everything the Overview tab shows, read through the same endpoints the
273314
+ * individual tabs use so the two never disagree. Each section is requested
273315
+ * only when its tab is on this profile, and every request names the viewed
273316
+ * user, so an admin previewing someone else sees that person's activity.
273317
+ */
273318
+ function useOverviewData(org, username, sections) {
273319
+ const isPreview = useIsProfilePreview(username);
273320
+ const currentUsername = useCurrentUsername();
273321
+ const hasScope = !!org && !!username;
273322
+ // ── Learning ───────────────────────────────────────────────────────────
273323
+ const learningSkip = !sections.learning || !hasScope;
273324
+ const enrolledQ = useGetUserEnrolledCoursesQuery({
273325
+ username,
273326
+ query: { page: 1, page_size: OVERVIEW_ENROLLMENT_PAGE_SIZE, platform_key: org },
273327
+ }, { skip: learningSkip });
273328
+ const learnerQ = useGetLearnerDetailsQuery({ username, platform_key: org, metrics: 'courses,time_spent' }, { skip: learningSkip });
273329
+ const programsQ = useGetUserEnrolledProgramsQuery([{ username, platformKey: org }], { skip: learningSkip });
273330
+ const pathwaysQ = useGetUserCatalogPathwaysQuery({ username, platform_key: org }, { skip: learningSkip });
273331
+ // ── Records: credentials are course records, so they follow the learning cards
273332
+ const credentialsQ = useGetUsersAsAssertionsQuery({ platformKey: org, userId: username, page: 1, pageSize: 1 }, { skip: learningSkip });
273333
+ // ── Conversations ──────────────────────────────────────────────────────
273334
+ const historyQ = useGetUserChatHistoryQuery({ org, userId: username, params: { page: 1, page_size: OVERVIEW_CONVERSATION_LIMIT } }, { skip: !sections.chatHistory || !hasScope });
273335
+ // ── AI usage ───────────────────────────────────────────────────────────
273336
+ const scope = { platformKey: org, username, date_filter: OVERVIEW_LLM_RANGE };
273337
+ const summaryQ = useUserLlmUsageSummary(scope, { skip: !sections.llmUsage });
273338
+ const spendQ = useUserLlmSpendOverTime({ ...scope, granularity: 'day' }, { skip: !sections.llmUsage });
273339
+ const byModelQ = useUserLlmCostByModel({ ...scope, limit: OVERVIEW_MODEL_LIMIT }, { skip: !sections.llmUsage });
273340
+ // ── Memory ─────────────────────────────────────────────────────────────
273341
+ // Addressed the way the Memory tab does it: your own feed by your username;
273342
+ // someone else's with the caller in the path and the viewed user as a param.
273343
+ const memoryParams = { page: 1, page_size: OVERVIEW_MEMORY_LIMIT };
273344
+ const memoriesQ = useGetGlobalMemoriesQuery(isPreview
273345
+ ? { org, userId: currentUsername, params: { ...memoryParams, user_id: username } }
273346
+ : { org, userId: username, params: memoryParams }, { skip: !sections.memory || !hasScope || (isPreview && !currentUsername) });
273347
+ const memorySettingsQ = useGetUserMemorySettingsQuery({ org, userId: username }, { skip: !sections.memory || !hasScope });
273348
+ const learning = useMemo(() => {
273349
+ var _a, _b, _c, _d, _e, _f, _g, _h;
273350
+ const enrolled = (_b = (_a = enrolledQ.data) === null || _a === void 0 ? void 0 : _a.results) !== null && _b !== void 0 ? _b : [];
273351
+ const details = (_c = learnerQ.data) === null || _c === void 0 ? void 0 : _c.data;
273352
+ const courses = sortCoursesByProgress((_d = details === null || details === void 0 ? void 0 : details.courses) !== null && _d !== void 0 ? _d : []);
273353
+ const summary = learnerQ.isError || !details ? null : summarizeLearning(courses);
273354
+ const programs = programsQ.data;
273355
+ const pathways = pathwaysQ.data;
273356
+ return {
273357
+ enabled: sections.learning,
273358
+ isLoading: !learningSkip && (enrolledQ.isLoading || learnerQ.isLoading),
273359
+ isError: enrolledQ.isError,
273360
+ isProgressUnavailable: learnerQ.isError,
273361
+ enrolledCount: (_f = (_e = enrolledQ.data) === null || _e === void 0 ? void 0 : _e.count) !== null && _f !== void 0 ? _f : enrolled.length,
273362
+ enrolled,
273363
+ courses,
273364
+ summary,
273365
+ timeSpentSecs: (_h = (_g = details === null || details === void 0 ? void 0 : details.time_spent) === null || _g === void 0 ? void 0 : _g.total_time_spent_secs) !== null && _h !== void 0 ? _h : null,
273366
+ programsCount: programsQ.isError ? null : programs ? programs.length : null,
273367
+ pathwaysCount: pathwaysQ.isError ? null : pathways ? pathways.length : null,
273368
+ };
273369
+ }, [sections.learning, learningSkip, enrolledQ, learnerQ, programsQ, pathwaysQ]);
273370
+ const records = useMemo(() => {
273371
+ var _a, _b, _c;
273372
+ const assertions = credentialsQ.data;
273373
+ return {
273374
+ isLoading: !learningSkip && credentialsQ.isLoading,
273375
+ credentialsCount: credentialsQ.isError
273376
+ ? null
273377
+ : assertions
273378
+ ? ((_c = (_a = assertions.count) !== null && _a !== void 0 ? _a : (_b = assertions.data) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0)
273379
+ : null,
273380
+ };
273381
+ }, [learningSkip, credentialsQ]);
273382
+ const conversations = useMemo(() => {
273383
+ var _a, _b, _c, _d;
273384
+ return ({
273385
+ enabled: sections.chatHistory,
273386
+ isLoading: sections.chatHistory && historyQ.isLoading,
273387
+ isError: historyQ.isError,
273388
+ isForbidden: statusOf(historyQ.error) === 403,
273389
+ count: (_b = (_a = historyQ.data) === null || _a === void 0 ? void 0 : _a.count) !== null && _b !== void 0 ? _b : 0,
273390
+ recent: (_d = (_c = historyQ.data) === null || _c === void 0 ? void 0 : _c.results) !== null && _d !== void 0 ? _d : [],
273391
+ });
273392
+ }, [sections.chatHistory, historyQ]);
273393
+ const usage = useMemo(() => ({
273394
+ enabled: sections.llmUsage,
273395
+ isLoading: summaryQ.isLoading || summaryQ.isIdle,
273396
+ error: summaryQ.error,
273397
+ isEmpty: summaryQ.isEmpty,
273398
+ summary: summaryQ.summary,
273399
+ points: spendQ.points,
273400
+ isSpendLoading: spendQ.isLoading || spendQ.isIdle,
273401
+ spendError: spendQ.error,
273402
+ models: byModelQ.models,
273403
+ isBreakdownLoading: byModelQ.isLoading || byModelQ.isIdle,
273404
+ breakdownError: byModelQ.error,
273405
+ }), [sections.llmUsage, summaryQ, spendQ, byModelQ]);
273406
+ const memory = useMemo(() => {
273407
+ var _a, _b, _c, _d, _e;
273408
+ return ({
273409
+ enabled: sections.memory,
273410
+ isLoading: sections.memory && memoriesQ.isLoading,
273411
+ isError: memoriesQ.isError,
273412
+ count: (_b = (_a = memoriesQ.data) === null || _a === void 0 ? void 0 : _a.count) !== null && _b !== void 0 ? _b : 0,
273413
+ recent: (_d = (_c = memoriesQ.data) === null || _c === void 0 ? void 0 : _c.results) !== null && _d !== void 0 ? _d : [],
273414
+ settings: (_e = memorySettingsQ.data) !== null && _e !== void 0 ? _e : null,
273415
+ });
273416
+ }, [sections.memory, memoriesQ, memorySettingsQ]);
273417
+ const isRefreshing = enrolledQ.isFetching ||
273418
+ learnerQ.isFetching ||
273419
+ historyQ.isFetching ||
273420
+ summaryQ.isFetching ||
273421
+ spendQ.isFetching ||
273422
+ byModelQ.isFetching ||
273423
+ memoriesQ.isFetching;
273424
+ const refetch = () => {
273425
+ if (!learningSkip) {
273426
+ enrolledQ.refetch();
273427
+ learnerQ.refetch();
273428
+ }
273429
+ if (sections.chatHistory && hasScope)
273430
+ historyQ.refetch();
273431
+ if (sections.llmUsage) {
273432
+ summaryQ.refetch();
273433
+ spendQ.refetch();
273434
+ byModelQ.refetch();
273435
+ }
273436
+ if (sections.memory && hasScope)
273437
+ memoriesQ.refetch();
273438
+ };
273439
+ return { learning, records, conversations, usage, memory, isRefreshing, refetch };
273440
+ }
273441
+
273442
+ const CARD = 'rounded-xl border border-gray-200 bg-white dark:border-gray-800 dark:bg-gray-950';
273443
+ // One hue, light → dark, for the ordered completion states; bars are the
273444
+ // profile's single-series blue. The "not started" share is the ring's track.
273445
+ const COMPLETED_COLOR = CHART_ORDINAL_RAMP[2];
273446
+ const IN_PROGRESS_COLOR = CHART_ORDINAL_RAMP[0];
273447
+ const BAR_COLOR = CHART_SERIES_COLORS[0];
273448
+ const RING_SIZE = 120;
273449
+ const RING_STROKE = 12;
273450
+ /** Rows kept in the model breakdown before the tail folds into "Other". */
273451
+ const BREAKDOWN_ROWS = 3;
273452
+ // ---------------------------------------------------------------------------
273453
+ // Building blocks
273454
+ // ---------------------------------------------------------------------------
273455
+ function StatTile({ icon: Icon, label, value, sub, loading, }) {
273456
+ return (jsxs("div", { className: cn(CARD, 'flex flex-col gap-2 p-4'), children: [jsxs("p", { className: "flex items-center gap-1.5 text-[13px] font-medium text-gray-500 dark:text-gray-400", children: [jsx(Icon, { className: "h-4 w-4 flex-shrink-0 text-gray-400", "aria-hidden": "true" }), jsx("span", { className: "truncate", children: label })] }), loading ? (jsxs(Fragment$1, { children: [jsx(Skeleton, { className: "h-7 w-24" }), jsx(Skeleton, { className: "h-4 w-20" })] })) : (jsxs(Fragment$1, { children: [jsx("p", { className: "text-[26px] font-semibold leading-tight tracking-tight text-gray-900 tabular-nums dark:text-gray-100", children: value }), jsx("p", { className: "min-h-[1rem] truncate text-xs text-gray-500 tabular-nums dark:text-gray-400", children: sub })] }))] }));
273457
+ }
273458
+ function ViewLink({ label, onClick }) {
273459
+ if (!onClick)
273460
+ return null;
273461
+ return (jsxs(Button$1, { variant: "ghost", size: "sm", onClick: onClick, className: "h-8 gap-1 px-2 text-[13px] font-medium text-blue-600 hover:bg-blue-50 hover:text-blue-700 dark:text-blue-400 dark:hover:bg-blue-950", children: [label, jsx(ArrowRight, { className: "h-3.5 w-3.5", "aria-hidden": "true" })] }));
273462
+ }
273463
+ function SectionCard$1({ title, subtitle, aside, action, children, className, bodyClassName, testId, }) {
273464
+ const headingId = useId$2();
273465
+ return (jsxs("section", { className: cn(CARD, className), "aria-labelledby": headingId, "data-testid": testId, children: [jsxs("div", { className: "flex flex-wrap items-start justify-between gap-x-4 gap-y-2 px-5 pt-5", children: [jsxs("div", { className: "min-w-0", children: [jsx("h4", { id: headingId, className: "text-[15px] font-semibold text-gray-900 dark:text-gray-100", children: title }), subtitle && (jsx("p", { className: "mt-0.5 text-[13px] text-gray-500 dark:text-gray-400", children: subtitle }))] }), (aside || action) && (jsxs("div", { className: "flex items-center gap-3", children: [aside, action] }))] }), jsx("div", { className: cn('px-5 pb-5 pt-4', bodyClassName), children: children })] }));
273466
+ }
273467
+ /** A section's empty or failed state, sized to the card it sits in. */
273468
+ function SectionMessage({ icon: Icon, tone = 'neutral', children, }) {
273469
+ return (jsxs("p", { className: "flex items-center justify-center gap-2 py-8 text-center text-sm text-gray-500 dark:text-gray-400", role: tone === 'error' ? 'alert' : undefined, children: [jsx(Icon, { className: cn('h-4 w-4 flex-shrink-0', tone === 'error' ? 'text-red-600' : 'text-gray-400'), "aria-hidden": "true" }), children] }));
273470
+ }
273471
+ function RecordChip({ icon: Icon, label, onClick, }) {
273472
+ const className = cn('inline-flex h-9 items-center gap-2 rounded-lg border border-gray-200 bg-white px-3 text-[13px] font-medium text-gray-700', 'dark:border-gray-800 dark:bg-gray-950 dark:text-gray-300', onClick &&
273473
+ 'transition-colors hover:bg-gray-50 hover:text-gray-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 dark:hover:bg-gray-900');
273474
+ const body = (jsxs(Fragment$1, { children: [jsx(Icon, { className: "h-4 w-4 flex-shrink-0 text-gray-400", "aria-hidden": "true" }), label, onClick && jsx(ArrowRight, { className: "h-3.5 w-3.5 text-gray-400", "aria-hidden": "true" })] }));
273475
+ return onClick ? (jsx("button", { type: "button", onClick: onClick, className: className, children: body })) : (jsx("span", { className: className, children: body }));
273476
+ }
273477
+ function ProgressBar({ value, label }) {
273478
+ return (jsx("span", { role: "progressbar", "aria-label": label, "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": value, className: "block h-1.5 w-full overflow-hidden rounded-full bg-gray-100 dark:bg-gray-800", children: jsx("span", { className: "block h-full rounded-full", style: { width: `${value}%`, background: BAR_COLOR } }) }));
273479
+ }
273480
+ function StatusPill({ on }) {
273481
+ const t = useT();
273482
+ return (jsxs("span", { className: cn('inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[11px] font-semibold', on
273483
+ ? 'bg-green-50 text-green-700 dark:bg-green-950 dark:text-green-300'
273484
+ : 'bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-300'), children: [jsx("span", { className: cn('h-1.5 w-1.5 rounded-full', on ? 'bg-green-600' : 'bg-gray-400'), "aria-hidden": "true" }), on ? t('profileOverviewTab.stateOn') : t('profileOverviewTab.stateOff')] }));
273485
+ }
273486
+ /**
273487
+ * Completed / in progress / not started as a ring, with the counts beside it
273488
+ * so the shares are never read from colour alone.
273489
+ */
273490
+ function CompletionRing({ summary }) {
273491
+ const t = useT();
273492
+ const radius = (RING_SIZE - RING_STROKE) / 2;
273493
+ const circumference = 2 * Math.PI * radius;
273494
+ const share = (count) => (summary.total ? count / summary.total : 0);
273495
+ const completed = share(summary.completed);
273496
+ const inProgress = share(summary.inProgress);
273497
+ // A 2px breathing space between adjacent fills, only when there are two.
273498
+ const gap = [completed, inProgress, share(summary.notStarted)].filter((s) => s > 0).length > 1 ? 2 : 0;
273499
+ const arc = (fraction, offset, color) => (jsx("circle", { cx: RING_SIZE / 2, cy: RING_SIZE / 2, r: radius, fill: "none", stroke: color, strokeWidth: RING_STROKE, strokeDasharray: `${Math.max(0, fraction * circumference - gap)} ${circumference}`, strokeDashoffset: -(offset * circumference + gap / 2) }));
273500
+ const legend = [
273501
+ {
273502
+ key: 'completed',
273503
+ label: t('profileOverviewTab.legendCompleted'),
273504
+ count: summary.completed,
273505
+ swatch: COMPLETED_COLOR,
273506
+ },
273507
+ {
273508
+ key: 'inProgress',
273509
+ label: t('profileOverviewTab.legendInProgress'),
273510
+ count: summary.inProgress,
273511
+ swatch: IN_PROGRESS_COLOR,
273512
+ },
273513
+ {
273514
+ key: 'notStarted',
273515
+ label: t('profileOverviewTab.legendNotStarted'),
273516
+ count: summary.notStarted,
273517
+ swatch: '',
273518
+ },
273519
+ ];
273520
+ return (jsxs("div", { className: "flex items-center gap-5", "data-testid": "completion-ring", children: [jsxs("div", { className: "relative flex-shrink-0", style: { width: RING_SIZE, height: RING_SIZE }, children: [jsxs("svg", { width: RING_SIZE, height: RING_SIZE, viewBox: `0 0 ${RING_SIZE} ${RING_SIZE}`, role: "img", "aria-label": t('profileOverviewTab.ringAria', {
273521
+ completed: summary.completed,
273522
+ total: summary.total,
273523
+ }), className: "-rotate-90", children: [jsx("circle", { cx: RING_SIZE / 2, cy: RING_SIZE / 2, r: radius, fill: "none", strokeWidth: RING_STROKE, className: "stroke-gray-100 dark:stroke-gray-800" }), inProgress > 0 && arc(inProgress, completed, IN_PROGRESS_COLOR), completed > 0 && arc(completed, 0, COMPLETED_COLOR)] }), jsxs("div", { className: "absolute inset-0 flex flex-col items-center justify-center", "aria-hidden": "true", children: [jsxs("span", { className: "text-xl font-semibold leading-none tabular-nums text-gray-900 dark:text-gray-100", children: [summary.completed, jsxs("span", { className: "text-sm font-medium text-gray-400", children: ["/", summary.total] })] }), jsx("span", { className: "mt-1 text-[11px] text-gray-500 dark:text-gray-400", children: t('profileOverviewTab.legendCompleted') })] })] }), jsx("ul", { className: "space-y-1.5 text-[13px]", children: legend.map((row) => (jsxs("li", { className: "flex items-center gap-2", children: [jsx("span", { className: cn('h-2.5 w-2.5 flex-shrink-0 rounded-[2px]', !row.swatch && 'bg-gray-200 dark:bg-gray-700'), style: row.swatch ? { background: row.swatch } : undefined, "aria-hidden": "true" }), jsx("span", { className: "text-gray-600 dark:text-gray-300", children: row.label }), jsx("span", { className: "ml-auto pl-3 font-semibold tabular-nums text-gray-900 dark:text-gray-100", children: row.count })] }, row.key))) })] }));
273524
+ }
273525
+ function CourseRow({ course, onOpen }) {
273526
+ var _a, _b, _c;
273527
+ const t = useT();
273528
+ const name = course.name || course.course_id;
273529
+ const percent = courseProgressPercent(course);
273530
+ const completed = isCourseCompleted(course);
273531
+ return (jsx("li", { children: jsxs("button", { type: "button", onClick: onOpen, "aria-label": t('profileOverviewTab.viewProgress', { name }), className: "flex w-full flex-col gap-2 rounded-lg px-3 py-2.5 text-left transition-colors hover:bg-gray-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 dark:hover:bg-gray-900", children: [jsxs("div", { className: "flex w-full items-center justify-between gap-3", children: [jsx("span", { className: "min-w-0 truncate text-sm font-medium text-gray-900 dark:text-gray-100", title: name, children: name }), completed ? (jsxs("span", { className: "inline-flex flex-shrink-0 items-center gap-1 rounded-md bg-blue-50 px-1.5 py-0.5 text-[11px] font-semibold text-blue-700 dark:bg-blue-950 dark:text-blue-300", children: [jsx(CircleCheck, { className: "h-3 w-3", "aria-hidden": "true" }), ((_a = course.completion) === null || _a === void 0 ? void 0 : _a.passed) && !((_b = course.completion) === null || _b === void 0 ? void 0 : _b.completed)
273532
+ ? t('profileOverviewTab.coursePassed')
273533
+ : t('profileOverviewTab.courseCompleted')] })) : (jsxs("span", { className: "flex-shrink-0 text-[13px] tabular-nums text-gray-700 dark:text-gray-300", children: [percent, "%"] }))] }), jsx(ProgressBar, { value: percent, label: t('profileOverviewTab.courseProgressAria', { name, percent }) }), jsxs("div", { className: "flex flex-wrap gap-x-3 gap-y-0.5 text-xs text-gray-500 dark:text-gray-400", children: [jsx("span", { children: t('profileOverviewTab.courseEnrolledOn', {
273534
+ date: formatShortDate((_c = course.enrollment) === null || _c === void 0 ? void 0 : _c.created),
273535
+ }) }), course.time_spent_secs > 0 && (jsx("span", { children: t('profileOverviewTab.courseTimeSpent', {
273536
+ duration: formatDuration(course.time_spent_secs),
273537
+ }) }))] })] }) }));
273538
+ }
273539
+ /** Enrollment-only row, for when per-course progress could not be read. */
273540
+ function EnrollmentRow({ course }) {
273541
+ const t = useT();
273542
+ const name = course.course_name || course.course_id;
273543
+ return (jsxs("li", { className: "flex items-center justify-between gap-3 px-3 py-2.5", children: [jsxs("div", { className: "min-w-0", children: [jsx("p", { className: "truncate text-sm font-medium text-gray-900 dark:text-gray-100", title: name, children: name }), jsx("p", { className: "mt-0.5 text-xs text-gray-500 dark:text-gray-400", children: t('profileOverviewTab.courseEnrolledOn', { date: formatShortDate(course.created) }) })] }), jsx("span", { className: cn('flex-shrink-0 rounded-md px-1.5 py-0.5 text-[11px] font-semibold', course.active
273544
+ ? 'bg-blue-50 text-blue-700 dark:bg-blue-950 dark:text-blue-300'
273545
+ : 'bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-300'), children: course.active
273546
+ ? t('profileOverviewTab.enrollmentActive')
273547
+ : t('profileOverviewTab.enrollmentInactive') })] }));
273548
+ }
273549
+ function ConversationRow({ session }) {
273550
+ var _a;
273551
+ const t = useT();
273552
+ const title = conversationTitle(session, t('profileOverviewTab.conversation'));
273553
+ const agent = session.mentor_name || t('profileOverviewTab.agent');
273554
+ const turns = (_a = session.message_count_human) !== null && _a !== void 0 ? _a : 0;
273555
+ const labels = useMemo(() => ({
273556
+ positive: t('chatHistoryChatHistoryTab.positive'),
273557
+ neutral: t('chatHistoryChatHistoryTab.neutral'),
273558
+ negative: t('chatHistoryChatHistoryTab.negative'),
273559
+ userSentiment: t('chatHistoryChatHistoryTab.userSentiment'),
273560
+ }), [t]);
273561
+ return (jsxs("li", { className: "flex items-start gap-3 py-3 first:pt-0 last:pb-0", "data-testid": "overview-conversation", children: [jsx("span", { className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-gray-100 text-gray-500 dark:bg-gray-800 dark:text-gray-400", "aria-hidden": "true", children: jsx(Bot, { className: "h-4 w-4" }) }), jsxs("div", { className: "min-w-0 flex-1", children: [jsxs("div", { className: "flex items-baseline justify-between gap-3", children: [jsx("span", { className: "min-w-0 truncate text-sm font-medium text-gray-900 dark:text-gray-100", title: title, children: title }), jsx("span", { className: "flex-shrink-0 text-xs text-gray-500 dark:text-gray-400", children: formatRelative(session.inserted_at) })] }), jsxs("p", { className: "mt-0.5 truncate text-xs text-gray-500 dark:text-gray-400", children: [agent, turns > 0 && ` · ${t('profileOverviewTab.messageCount', { count: turns })}`] }), jsx(ConversationTopics, { topics: session.topics, className: "mt-1.5", leading: jsx(ConversationSentiment, { sentiment: session.sentiment, labels: labels, compact: true }) })] })] }));
273562
+ }
273563
+ function MemoryRow({ memory }) {
273564
+ const t = useT();
273565
+ return (jsxs("li", { className: "flex items-start gap-3 py-3 first:pt-0 last:pb-0", "data-testid": "overview-memory-row", children: [jsx("span", { className: "mt-0.5 flex-shrink-0", children: memory.is_auto_generated ? (jsx(Bot, { className: "h-4 w-4 text-blue-500", "aria-label": t('memoryMemoryTab.autoGeneratedMemoryAriaLabel') })) : (jsx(User, { className: "h-4 w-4 text-gray-400", "aria-label": t('memoryMemoryTab.manuallyAddedMemoryAriaLabel') })) }), jsxs("div", { className: "min-w-0 flex-1", children: [jsx("p", { className: "line-clamp-2 text-sm text-gray-800 dark:text-gray-200", children: memory.content }), jsxs("p", { className: "mt-1 text-xs text-gray-400", children: [formatShortDate(memory.created_at), memory.is_auto_generated && (jsx("span", { className: "ml-2 inline-flex items-center rounded-full bg-blue-50 px-1.5 py-0.5 text-[10px] font-medium text-blue-600", children: t('memoryMemoryTab.autoBadge') }))] })] })] }));
273566
+ }
273567
+ function MemorySettingsList({ settings }) {
273568
+ const t = useT();
273569
+ const rows = [
273570
+ {
273571
+ key: 'capture',
273572
+ label: t('profileOverviewTab.memoryAutoCapture'),
273573
+ on: settings.auto_capture_enabled,
273574
+ },
273575
+ {
273576
+ key: 'responses',
273577
+ label: t('profileOverviewTab.memoryUseInResponses'),
273578
+ on: settings.use_memory_in_responses,
273579
+ },
273580
+ ];
273581
+ return (jsx("ul", { className: "space-y-2", children: rows.map((row) => (jsxs("li", { className: "flex items-center justify-between gap-3 rounded-lg border border-gray-200 px-3 py-2 text-[13px] dark:border-gray-800", children: [jsx("span", { className: "text-gray-700 dark:text-gray-300", children: row.label }), jsx(StatusPill, { on: row.on })] }, row.key))) }));
273582
+ }
273583
+ function ListSkeleton({ rows = 3, height = 'h-12' }) {
273584
+ return (jsx("div", { className: "flex flex-col gap-3", children: Array.from({ length: rows }, (_, i) => (jsx(Skeleton, { className: cn('w-full', height) }, i))) }));
273585
+ }
273586
+ /**
273587
+ * The profile "Overview" tab: a one-screen digest of the user's activity —
273588
+ * course enrollments and progress, conversations with AI agents, AI spend and
273589
+ * what the AI remembers — each card summarising one of the fuller tabs and
273590
+ * linking to it.
273591
+ */
273592
+ function OverviewTab({ org, username, isOwnProfile = true, sections, onNavigate, availableTabs, }) {
273593
+ var _a, _b, _c, _d;
273594
+ const t = useT();
273595
+ const data = useOverviewData(org, username, sections);
273596
+ const { learning, records, conversations, usage, memory } = data;
273597
+ const [selectedCourse, setSelectedCourse] = useState(null);
273598
+ const open = (target) => onNavigate && (!availableTabs || availableTabs.includes(target.tab))
273599
+ ? () => onNavigate(target)
273600
+ : undefined;
273601
+ const unavailable = t('profileOverviewTab.unavailable');
273602
+ const series = useMemo(() => buildSpendSeries(usage.points, OVERVIEW_LLM_RANGE), [usage.points]);
273603
+ const toRanked = (rows, fallback) => foldTail(rows.map((row, index) => ({
273604
+ key: row.label || `unknown-${index}`,
273605
+ label: row.label || fallback,
273606
+ totalCost: row.totalCost,
273607
+ count: row.count,
273608
+ })), BREAKDOWN_ROWS, t('profileLlmUsage.otherRow'));
273609
+ const modelRows = useMemo(() => toRanked(usage.models.map((row) => ({ ...row, label: row.model })), t('profileLlmUsage.unknownModel')),
273610
+ // eslint-disable-next-line react-hooks/exhaustive-deps
273611
+ [usage.models, t]);
273612
+ const sumCost = (rows) => rows.reduce((sum, row) => sum + row.totalCost, 0);
273613
+ // ── Tiles ──────────────────────────────────────────────────────────────
273614
+ const tiles = [];
273615
+ if (learning.enabled) {
273616
+ const summary = learning.summary;
273617
+ tiles.push(jsx(StatTile, { icon: GraduationCap, label: t('profileOverviewTab.kpiEnrolled'), value: learning.isError ? '—' : formatInteger(learning.enrolledCount), sub: learning.isError
273618
+ ? unavailable
273619
+ : summary
273620
+ ? t('profileOverviewTab.kpiEnrolledSub', { count: summary.inProgress })
273621
+ : t('profileOverviewTab.kpiEnrolledSubAll'), loading: learning.isLoading }, "enrolled"), jsx(StatTile, { icon: CircleCheck, label: t('profileOverviewTab.kpiCompleted'), value: summary ? formatInteger(summary.completed) : '—', sub: summary
273622
+ ? t('profileOverviewTab.kpiCompletedSub', {
273623
+ percent: percentOf(summary.completed, summary.total),
273624
+ })
273625
+ : unavailable, loading: learning.isLoading }, "completed"), jsx(StatTile, { icon: TrendingUp, label: t('profileOverviewTab.kpiProgress'), value: summary ? `${summary.averageProgress}%` : '—', sub: summary ? t('profileOverviewTab.kpiProgressSub') : unavailable, loading: learning.isLoading }, "progress"), jsx(StatTile, { icon: Clock, label: t('profileOverviewTab.kpiTimeSpent'), value: learning.isProgressUnavailable ? '—' : formatDuration(learning.timeSpentSecs), sub: learning.isProgressUnavailable ? unavailable : t('profileOverviewTab.kpiTimeSpentSub'), loading: learning.isLoading }, "time"));
273626
+ }
273627
+ if (conversations.enabled) {
273628
+ const last = conversations.recent[0];
273629
+ tiles.push(jsx(StatTile, { icon: MessageSquare, label: t('profileOverviewTab.kpiConversations'), value: conversations.isError ? '—' : formatInteger(conversations.count), sub: conversations.isError
273630
+ ? unavailable
273631
+ : last
273632
+ ? t('profileOverviewTab.kpiConversationsLast', {
273633
+ when: formatRelative(last.inserted_at),
273634
+ })
273635
+ : t('profileOverviewTab.kpiConversationsSub'), loading: conversations.isLoading }, "conversations"));
273636
+ }
273637
+ if (usage.enabled) {
273638
+ const totals = usage.summary;
273639
+ const failed = !!usage.error;
273640
+ tiles.push(jsx(StatTile, { icon: Coins, label: t('profileOverviewTab.kpiSpend'), value: failed ? '—' : formatCost((_a = totals === null || totals === void 0 ? void 0 : totals.totalCost) !== null && _a !== void 0 ? _a : 0), sub: failed ? unavailable : t('profileOverviewTab.kpiSpendSub'), loading: usage.isLoading }, "spend"), jsx(StatTile, { icon: Zap, label: t('profileOverviewTab.kpiRequests'), value: failed ? '—' : formatInteger((_b = totals === null || totals === void 0 ? void 0 : totals.count) !== null && _b !== void 0 ? _b : 0), sub: failed
273641
+ ? unavailable
273642
+ : t('profileOverviewTab.kpiRequestsSub', {
273643
+ tokens: formatCompact((_c = totals === null || totals === void 0 ? void 0 : totals.totalTokens) !== null && _c !== void 0 ? _c : 0),
273644
+ }), loading: usage.isLoading }, "requests"));
273645
+ }
273646
+ if (memory.enabled) {
273647
+ tiles.push(jsx(StatTile, { icon: Archive, label: t('profileOverviewTab.kpiMemories'), value: memory.isError ? '—' : formatInteger(memory.count), sub: memory.isError
273648
+ ? unavailable
273649
+ : memory.settings
273650
+ ? memory.settings.auto_capture_enabled
273651
+ ? t('profileOverviewTab.kpiMemoriesSubOn')
273652
+ : t('profileOverviewTab.kpiMemoriesSubOff')
273653
+ : t('profileOverviewTab.kpiMemoriesSub'), loading: memory.isLoading }, "memories"));
273654
+ }
273655
+ // ── Records strip: course records, shown only where there is something ─
273656
+ const chips = [];
273657
+ if (learning.enabled && records.credentialsCount) {
273658
+ chips.push(jsx(RecordChip, { icon: Award, label: t('profileOverviewTab.recordsCredentials', { count: records.credentialsCount }), onClick: open({ tab: 'education', educationSubTab: 'credentials' }) }, "credentials"));
273659
+ }
273660
+ if (learning.enabled && learning.programsCount) {
273661
+ chips.push(jsx(RecordChip, { icon: Layers, label: t('profileOverviewTab.recordsPrograms', { count: learning.programsCount }), onClick: open({ tab: 'gradebook', gradebookType: 'programs' }) }, "programs"));
273662
+ }
273663
+ if (learning.enabled && learning.pathwaysCount) {
273664
+ chips.push(jsx(RecordChip, { icon: Route, label: t('profileOverviewTab.recordsPathways', { count: learning.pathwaysCount }), onClick: open({ tab: 'gradebook', gradebookType: 'pathways' }) }, "pathways"));
273665
+ }
273666
+ // ── Learning section ───────────────────────────────────────────────────
273667
+ let learningBody = null;
273668
+ if (learning.enabled) {
273669
+ const detailed = learning.courses;
273670
+ const shown = detailed.length ? detailed.slice(0, OVERVIEW_COURSE_LIMIT) : [];
273671
+ const fallback = detailed.length ? [] : learning.enrolled.slice(0, OVERVIEW_COURSE_LIMIT);
273672
+ const total = detailed.length ? detailed.length : learning.enrolledCount;
273673
+ const remaining = Math.max(0, total - (shown.length || fallback.length));
273674
+ if (learning.isLoading) {
273675
+ learningBody = (jsxs("div", { className: "grid grid-cols-1 gap-6 lg:grid-cols-[auto_minmax(0,1fr)]", children: [jsx(Skeleton, { className: "h-[120px] w-[260px] rounded-full" }), jsx(ListSkeleton, { rows: 3, height: "h-14" })] }));
273676
+ }
273677
+ else if (learning.isError) {
273678
+ learningBody = (jsx(SectionMessage, { icon: CircleAlert, tone: "error", children: t('profileOverviewTab.learningError') }));
273679
+ }
273680
+ else if (!shown.length && !fallback.length) {
273681
+ learningBody = (jsx(SectionMessage, { icon: GraduationCap, children: t('profileOverviewTab.learningEmpty') }));
273682
+ }
273683
+ else {
273684
+ learningBody = (jsxs("div", { className: "grid grid-cols-1 gap-6 lg:grid-cols-[auto_minmax(0,1fr)]", children: [learning.summary && jsx(CompletionRing, { summary: learning.summary }), jsxs("div", { className: "min-w-0", children: [learning.isProgressUnavailable && (jsxs("p", { className: "mb-2 flex items-center gap-1.5 text-xs text-gray-500 dark:text-gray-400", children: [jsx(CircleAlert, { className: "h-3.5 w-3.5", "aria-hidden": "true" }), t('profileOverviewTab.learningProgressUnavailable')] })), jsxs("ul", { className: "-mx-3 divide-y divide-gray-100 dark:divide-gray-800", children: [shown.map((course) => (jsx(CourseRow, { course: course, onOpen: () => setSelectedCourse({ id: course.course_id, name: course.name }) }, course.course_id))), fallback.map((course) => (jsx(EnrollmentRow, { course: course }, course.course_id)))] }), remaining > 0 && (jsx("p", { className: "mt-3 text-xs text-gray-500 dark:text-gray-400", children: t('profileOverviewTab.moreCourses', { count: remaining }) }))] })] }));
273685
+ }
273686
+ }
273687
+ // ── AI usage section ───────────────────────────────────────────────────
273688
+ const usageErrorCopy = (error) => error.kind === 'forbidden' || error.kind === 'not_found'
273689
+ ? t('profileOverviewTab.usageForbidden')
273690
+ : t('profileOverviewTab.usageError');
273691
+ let usageBody = null;
273692
+ if (usage.enabled) {
273693
+ if (usage.isLoading) {
273694
+ usageBody = (jsxs("div", { className: "flex flex-1 flex-col gap-5", children: [jsx(Skeleton, { className: "h-[200px] w-full" }), jsx("div", { className: "mt-auto", children: jsx(BreakdownSkeleton, {}) })] }));
273695
+ }
273696
+ else if (usage.error) {
273697
+ usageBody = (jsx(SectionMessage, { icon: CircleAlert, tone: "error", children: usageErrorCopy(usage.error) }));
273698
+ }
273699
+ else if (usage.isEmpty) {
273700
+ usageBody = (jsx(SectionMessage, { icon: Inbox, children: t('profileOverviewTab.usageEmpty') }));
273701
+ }
273702
+ else {
273703
+ let plot;
273704
+ // A message (no spend, failed series) centres in the room the chart
273705
+ // would have taken; the chart itself keeps its natural height.
273706
+ let plotIsMessage = true;
273707
+ if (usage.isSpendLoading) {
273708
+ plot = jsx(Skeleton, { className: "h-[200px] w-full" });
273709
+ }
273710
+ else if (usage.spendError) {
273711
+ plot = (jsx(SectionMessage, { icon: CircleAlert, tone: "error", children: usageErrorCopy(usage.spendError) }));
273712
+ }
273713
+ else if (series.every((point) => point.totalCost === 0)) {
273714
+ // Requests happened but none were billed: a flat chart on a $1 axis
273715
+ // looks broken, so say it instead.
273716
+ plot = jsx(SectionMessage, { icon: Inbox, children: t('profileOverviewTab.usageNoSpend') });
273717
+ }
273718
+ else {
273719
+ plot = jsx(SpendChart, { points: series, granularity: "day" });
273720
+ plotIsMessage = false;
273721
+ }
273722
+ const breakdown = (title, rows, colorFor, testId) => (jsxs("div", { className: "min-w-0", "data-testid": testId, children: [jsx("h5", { className: "mb-3 text-[13px] font-semibold text-gray-700 dark:text-gray-300", children: title }), usage.isBreakdownLoading ? (jsx(BreakdownSkeleton, {})) : usage.breakdownError ? (jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: t('profileLlmUsage.sectionError') })) : rows.length === 0 ? (jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: t('profileLlmUsage.breakdownEmpty') })) : (jsx(RankedBars, { rows: rows, total: sumCost(rows), colorFor: colorFor }))] }));
273723
+ // The breakdowns sit at the foot of the card, so when the card
273724
+ // stretches to match its neighbour the space opens between the plot
273725
+ // and the breakdowns rather than piling up under them.
273726
+ usageBody = (jsxs("div", { className: "flex flex-1 flex-col gap-5", children: [jsx("div", { className: cn(plotIsMessage && 'flex flex-1 items-center justify-center'), children: plot }), jsx("div", { className: "mt-auto border-t border-gray-100 pt-4 dark:border-gray-800", children: breakdown(t('profileLlmUsage.byModelTitle'), modelRows, () => BAR_COLOR, 'overview-usage-by-model') })] }));
273727
+ }
273728
+ }
273729
+ // ── Conversations section ──────────────────────────────────────────────
273730
+ let conversationsBody = null;
273731
+ if (conversations.enabled) {
273732
+ if (conversations.isLoading) {
273733
+ conversationsBody = jsx(ListSkeleton, { rows: 3 });
273734
+ }
273735
+ else if (conversations.isError) {
273736
+ conversationsBody = (jsx(SectionMessage, { icon: CircleAlert, tone: "error", children: conversations.isForbidden
273737
+ ? t('profileOverviewTab.conversationsForbidden')
273738
+ : t('profileOverviewTab.conversationsError') }));
273739
+ }
273740
+ else if (conversations.recent.length === 0) {
273741
+ conversationsBody = (jsx(SectionMessage, { icon: MessageSquare, children: t('profileOverviewTab.conversationsEmpty') }));
273742
+ }
273743
+ else {
273744
+ conversationsBody = (jsx("ul", { className: "divide-y divide-gray-100 dark:divide-gray-800", children: conversations.recent.slice(0, OVERVIEW_CONVERSATION_LIMIT).map((session) => (jsx(ConversationRow, { session: session }, session.id))) }));
273745
+ }
273746
+ }
273747
+ // ── Memory section ─────────────────────────────────────────────────────
273748
+ let memoryBody = null;
273749
+ if (memory.enabled) {
273750
+ let list;
273751
+ if (memory.isLoading) {
273752
+ list = jsx(ListSkeleton, { rows: 3 });
273753
+ }
273754
+ else if (memory.isError) {
273755
+ list = (jsx(SectionMessage, { icon: CircleAlert, tone: "error", children: t('profileOverviewTab.memoryError') }));
273756
+ }
273757
+ else if (memory.recent.length === 0) {
273758
+ list = jsx(SectionMessage, { icon: Archive, children: t('profileOverviewTab.memoryEmpty') });
273759
+ }
273760
+ else {
273761
+ list = (jsx("ul", { className: "divide-y divide-gray-100 dark:divide-gray-800", children: memory.recent.slice(0, OVERVIEW_MEMORY_LIMIT).map((item) => (jsx(MemoryRow, { memory: item }, item.id))) }));
273762
+ }
273763
+ memoryBody = memory.settings ? (jsxs("div", { className: "grid grid-cols-1 gap-5 lg:grid-cols-[minmax(0,1fr)_260px]", children: [jsx("div", { className: "min-w-0", children: list }), jsx(MemorySettingsList, { settings: memory.settings })] })) : (list);
273764
+ }
273765
+ const twoUp = usage.enabled && conversations.enabled;
273766
+ return (jsxs("div", { className: "flex flex-col gap-5", "data-testid": "profile-overview-tab", children: [jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [jsx("p", { className: "text-[13px] text-gray-500 dark:text-gray-400", children: isOwnProfile
273767
+ ? t('profileOverviewTab.scopeSelf')
273768
+ : t('profileOverviewTab.scopeUser', { username }) }), jsx(Button$1, { variant: "outline", size: "icon", className: "h-9 w-9", onClick: data.refetch, disabled: data.isRefreshing, "aria-label": t('profileOverviewTab.refresh'), title: t('profileOverviewTab.refresh'), children: jsx(RefreshCw, { className: cn('h-4 w-4', data.isRefreshing && 'animate-spin'), "aria-hidden": "true" }) })] }), tiles.length > 0 && (jsx("div", { className: "grid grid-cols-2 gap-3 md:grid-cols-4", "data-testid": "overview-tiles", children: tiles })), ((learning.enabled && records.isLoading) || chips.length > 0) && (jsx("div", { role: "group", "aria-label": t('profileOverviewTab.recordsLabel'), className: "flex flex-wrap gap-2", "data-testid": "overview-records", children: records.isLoading ? (jsxs(Fragment$1, { children: [jsx(Skeleton, { className: "h-9 w-32 rounded-lg" }), jsx(Skeleton, { className: "h-9 w-32 rounded-lg" })] })) : (chips) })), learning.enabled && (jsx(SectionCard$1, { title: t('profileOverviewTab.learningTitle'), subtitle: t('profileOverviewTab.learningSubtitle'), action: jsx(ViewLink, { label: t('profileOverviewTab.viewGradebook'), onClick: open({ tab: 'gradebook', gradebookType: 'courses' }) }), testId: "overview-learning", children: learningBody })), (usage.enabled || conversations.enabled) && (jsxs("div", { className: cn('grid grid-cols-1 gap-5', twoUp && 'xl:grid-cols-2'), children: [usage.enabled && (jsx(SectionCard$1, { title: t('profileOverviewTab.usageTitle'), subtitle: t('profileOverviewTab.usageSubtitle'), aside: usage.summary && !usage.error && !usage.isLoading ? (jsx("span", { className: "text-[15px] font-semibold tabular-nums text-gray-900 dark:text-gray-100", children: formatCost(usage.summary.totalCost) })) : null, action: jsx(ViewLink, { label: t('profileOverviewTab.viewUsage'), onClick: open({ tab: 'llmUsage' }) }), className: "flex flex-col", bodyClassName: "flex flex-1 flex-col pt-2", testId: "overview-usage", children: usageBody })), conversations.enabled && (jsx(SectionCard$1, { title: t('profileOverviewTab.conversationsTitle'), subtitle: isOwnProfile
273769
+ ? t('profileOverviewTab.conversationsSubtitle')
273770
+ : t('profileOverviewTab.conversationsSubtitlePreview'), action: jsx(ViewLink, { label: t('profileOverviewTab.viewHistory'), onClick: open({ tab: 'chatHistory' }) }), testId: "overview-conversations", children: conversationsBody }))] })), memory.enabled && (jsx(SectionCard$1, { title: t('profileOverviewTab.memoryTitle'), subtitle: isOwnProfile
273771
+ ? t('profileOverviewTab.memorySubtitle')
273772
+ : t('profileOverviewTab.memorySubtitlePreview'), action: jsx(ViewLink, { label: t('profileOverviewTab.viewMemory'), onClick: open({ tab: 'memory' }) }), testId: "overview-memory", children: memoryBody })), jsx(EnrolledUserProgressModal, { open: !!selectedCourse, onOpenChange: (isOpen) => {
273773
+ if (!isOpen)
273774
+ setSelectedCourse(null);
273775
+ }, username: username, contentId: (_d = selectedCourse === null || selectedCourse === void 0 ? void 0 : selectedCourse.id) !== null && _d !== void 0 ? _d : '', contentName: selectedCourse === null || selectedCourse === void 0 ? void 0 : selectedCourse.name, metric: "course", tenantKey: org })] }));
273776
+ }
273777
+
272830
273778
  const tabId = (id, mobile) => (mobile ? `${id}-tab-mobile` : `${id}-tab`);
272831
273779
  /** Arrow/Home/End handling for the tab variant, with automatic activation. */
272832
273780
  function useTabKeyboard(items, onSelect, mobile) {
@@ -272934,6 +273882,7 @@ function setCoworkEnabled(enabled) {
272934
273882
  }
272935
273883
 
272936
273884
  const TAB_DESC_KEYS$1 = {
273885
+ overview: 'descOverview',
272937
273886
  basic: 'descBasic',
272938
273887
  social: 'descSocial',
272939
273888
  education: 'descEducation',
@@ -272949,6 +273898,7 @@ const TAB_DESC_KEYS$1 = {
272949
273898
  };
272950
273899
  // Neutral variants (no "your") shown when previewing another user's profile.
272951
273900
  const TAB_DESC_PREVIEW_KEYS = {
273901
+ overview: 'descOverviewPreview',
272952
273902
  basic: 'descBasicPreview',
272953
273903
  social: 'descSocialPreview',
272954
273904
  education: 'descEducationPreview',
@@ -272960,10 +273910,12 @@ const TAB_DESC_PREVIEW_KEYS = {
272960
273910
  chatHistory: 'descChatHistoryPreview',
272961
273911
  llmUsage: 'descLlmUsagePreview',
272962
273912
  };
273913
+ // Only these SPAs have courses, so only they get the Overview's learning cards.
273914
+ const COURSE_SPAS = ['lms', 'skills'];
272963
273915
  const LABEL_CLASS = 'text-sm font-medium text-gray-700 dark:text-gray-300';
272964
273916
  const FIELD_CLASS = 'h-10 w-full bg-white border-gray-300 text-sm text-gray-900 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-900 dark:border-gray-700 dark:text-gray-100';
272965
273917
  const PRIMARY_BUTTON_CLASS = 'bg-blue-600 text-white hover:bg-blue-700 focus-visible:ring-blue-500 disabled:bg-blue-600/60';
272966
- function Profile({ tenant, username, tenants, onClose, customization = {}, isAdmin = false, targetTab = 'basic', onAccountDeleted, enableMemoryTab = false, showLlmUsageTab = true, localLLMProps, currentSPA = '', }) {
273918
+ function Profile({ tenant, username, tenants, onClose, customization = {}, isAdmin = false, targetTab = 'basic', onAccountDeleted, enableMemoryTab = false, showLlmUsageTab = true, showOverviewTab = true, localLLMProps, currentSPA = '', }) {
272967
273919
  var _a, _b, _c, _d, _e, _f;
272968
273920
  const t = useT();
272969
273921
  const { data: memsearchStatus, isError: isMemsearchStatusError } = useGetMemsearchStatusQuery({ org: tenant, userId: username }, { skip: !enableMemoryTab });
@@ -272991,8 +273943,20 @@ function Profile({ tenant, username, tenants, onClose, customization = {}, isAdm
272991
273943
  const isLlmUsageVisible = showLlmUsageTab && !isPureWatcher(rbacPermissions, viewerTenant);
272992
273944
  // Add Advanced tab only when in Tauri app (Local Models is provided and available)
272993
273945
  const isAdvancedAvailable = (localLLMProps === null || localLLMProps === void 0 ? void 0 : localLLMProps.isAvailable) === true;
273946
+ const isCourseSpa = COURSE_SPAS.includes(currentSPA.toLowerCase());
272994
273947
  const TABS = [
272995
273948
  { id: 'basic', label: t('profileIndex.tabBasic'), icon: User, group: 'profile' },
273949
+ // The digest of every other tab, right after the landing tab.
273950
+ ...(showOverviewTab
273951
+ ? [
273952
+ {
273953
+ id: 'overview',
273954
+ label: t('profileIndex.tabOverview'),
273955
+ icon: LayoutDashboard,
273956
+ group: 'profile',
273957
+ },
273958
+ ]
273959
+ : []),
272996
273960
  { id: 'social', label: t('profileIndex.tabSocial'), icon: Globe, group: 'profile' },
272997
273961
  ...(isGradebookEnabled
272998
273962
  ? [
@@ -273104,6 +274068,9 @@ function Profile({ tenant, username, tenants, onClose, customization = {}, isAdm
273104
274068
  items: TABS.filter((tab) => tab.group === group),
273105
274069
  }));
273106
274070
  const [activeTab, setActiveTab] = useState(targetTab);
274071
+ // Content type the Gradebook opens on when the Overview sends the user
274072
+ // there; cleared again whenever a tab is picked from the navigation.
274073
+ const [gradebookType, setGradebookType] = useState();
273107
274074
  const [isHovering, setIsHovering] = useState(false);
273108
274075
  const fileInputRef = useRef(null);
273109
274076
  // Dialog states for education and experience
@@ -273111,6 +274078,20 @@ function Profile({ tenant, username, tenants, onClose, customization = {}, isAdm
273111
274078
  const [isExperienceDialogOpen, setIsExperienceDialogOpen] = useState(false);
273112
274079
  const [educationSubTab, setEducationSubTab] = useState('education');
273113
274080
  const [experienceSubTab, setExperienceSubTab] = useState('experience');
274081
+ const selectTab = (id) => {
274082
+ setGradebookType(undefined);
274083
+ setActiveTab(id);
274084
+ };
274085
+ // The Overview's links land on the exact sub-view: a Gradebook content
274086
+ // type or an Education sub-tab. A tab this profile lacks is ignored.
274087
+ const openFromOverview = (target) => {
274088
+ if (!TABS.some((tab) => tab.id === target.tab))
274089
+ return;
274090
+ if (target.educationSubTab)
274091
+ setEducationSubTab(target.educationSubTab);
274092
+ setGradebookType(target.gradebookType);
274093
+ setActiveTab(target.tab);
274094
+ };
273114
274095
  const { basicForm, socialForm, isUserMetadataLoading, userMetadata, handleProfileImageUpload, isUploadingProfileImage, userMetadataEdx, isUserMetadataEdxLoading, FACEBOOK_URL_PREFIX, X_URL_PREFIX, LINKEDIN_URL_PREFIX, handleSocialLinkChange, socialValidators, basicValidators, } = useProfile(username, { platformKey: tenant });
273115
274096
  useEffect(() => {
273116
274097
  const firstInput = document.getElementById('fullName');
@@ -273208,7 +274189,7 @@ function Profile({ tenant, username, tenants, onClose, customization = {}, isAdm
273208
274189
  return (jsxs(Fragment$1, { children: [jsxs("div", { className: "relative mb-0", children: [jsx("div", { className: "pointer-events-none absolute inset-y-0 left-2 flex items-center", "aria-hidden": "true", children: jsx("div", { className: cn('flex h-7 w-7 items-center justify-center rounded-md text-white', badge.className), children: jsx("span", { className: cn('font-bold', badge.textClassName), children: badge.text }) }) }), jsx(Input, { id: id, className: cn(FIELD_CLASS, 'pl-12'), placeholder: placeholder, value: field.state.value, onChange: (e) => handleSocialLinkChange(e.target.value, field.handleChange, prefix), disabled: socialForm.state.isSubmitting || isReadOnly })] }), jsx("p", { className: "text-sm text-red-600 dark:text-red-400", role: ((_a = field.state.meta.errors) === null || _a === void 0 ? void 0 : _a.length) ? 'alert' : undefined, "aria-live": "polite", children: field.state.meta.errors })] }));
273209
274190
  },
273210
274191
  })] }));
273211
- return (jsxs(SettingsShell, { sidebarHeader: sidebarHeader, sidebarNav: jsx(SettingsSidebarNav, { groups: navGroups, activeId: activeTab, onSelect: setActiveTab, variant: "tabs", ariaLabel: t('profileIndex.ariaProfileTabs') }), mobileHeader: mobileHeader, mobileNav: jsx(SettingsMobileNav, { groups: navGroups, activeId: activeTab, onSelect: setActiveTab, variant: "tabs", ariaLabel: t('profileIndex.ariaProfileTabsMobile') }),
274192
+ return (jsxs(SettingsShell, { sidebarHeader: sidebarHeader, sidebarNav: jsx(SettingsSidebarNav, { groups: navGroups, activeId: activeTab, onSelect: selectTab, variant: "tabs", ariaLabel: t('profileIndex.ariaProfileTabs') }), mobileHeader: mobileHeader, mobileNav: jsx(SettingsMobileNav, { groups: navGroups, activeId: activeTab, onSelect: selectTab, variant: "tabs", ariaLabel: t('profileIndex.ariaProfileTabsMobile') }),
273212
274193
  // Render the tab's label rather than the id — every label is already
273213
274194
  // cased correctly.
273214
274195
  title: (_f = (_e = TABS.find((tab) => tab.id === activeTab)) === null || _e === void 0 ? void 0 : _e.label) !== null && _f !== void 0 ? _f : activeTab, description: tabDescription(activeTab), panelProps: {
@@ -273220,7 +274201,15 @@ function Profile({ tenant, username, tenants, onClose, customization = {}, isAdm
273220
274201
  // The education tab will handle refetching
273221
274202
  } }), jsx(ExperienceDialog, { open: isExperienceDialogOpen, onOpenChange: setIsExperienceDialogOpen, experience: undefined, org: tenant, username: username, onComplete: () => {
273222
274203
  // The experience tab will handle refetching
273223
- } }), jsx(ToastProvider, {})] }), children: [activeTab === 'basic' && (jsxs("form", { onSubmit: (formEvent) => {
274204
+ } }), jsx(ToastProvider, {})] }), children: [showOverviewTab && activeTab === 'overview' && (jsx(OverviewTab, { org: tenant, username: username, isOwnProfile: !isReadOnly,
274205
+ // Each card mirrors a tab, so a card only appears where its tab does;
274206
+ // the learning cards also need an SPA that has courses at all.
274207
+ sections: {
274208
+ learning: isCourseSpa,
274209
+ chatHistory: isChatHistoryVisible,
274210
+ llmUsage: isLlmUsageVisible,
274211
+ memory: isMemoryEnabled,
274212
+ }, availableTabs: TABS.map((tab) => tab.id), onNavigate: openFromOverview })), activeTab === 'basic' && (jsxs("form", { onSubmit: (formEvent) => {
273224
274213
  formEvent.preventDefault();
273225
274214
  formEvent.stopPropagation();
273226
274215
  if (isReadOnly)
@@ -273287,7 +274276,9 @@ function Profile({ tenant, username, tenants, onClose, customization = {}, isAdm
273287
274276
  prefix: X_URL_PREFIX,
273288
274277
  badge: { className: 'bg-black', text: 'X', textClassName: 'text-sm' },
273289
274278
  validator: socialValidators.x,
273290
- })] })), activeTab === 'education' && (jsxs(Tabs, { value: educationSubTab, onValueChange: setEducationSubTab, className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxs(TabsList, { children: [jsx(TabsTrigger, { value: "education", children: t('profileIndex.tabEducation') }), jsx(TabsTrigger, { value: "credentials", children: t('gradebookGradebookTab.typeCredentials') }), jsx(TabsTrigger, { value: "skills", children: t('gradebookGradebookTab.typeSkills') })] }), headerAddButton] }), jsx(TabsContent, { value: "education", children: jsx(EducationTab, { org: tenant, username: username }) }), jsx(TabsContent, { value: "credentials", children: jsx(CredentialsList, { org: tenant, username: username }) }), jsx(TabsContent, { value: "skills", children: jsx(SkillsList, { org: tenant, username: username }) })] })), activeTab === 'gradebook' && jsx(GradebookTab, { org: tenant, username: username }), activeTab === 'experience' && (jsxs(Tabs, { value: experienceSubTab, onValueChange: setExperienceSubTab, className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxs(TabsList, { children: [jsx(TabsTrigger, { value: "experience", children: t('profileIndex.tabExperience') }), jsx(TabsTrigger, { value: "resume", children: t('profileIndex.tabResume') })] }), headerAddButton] }), jsx(TabsContent, { value: "experience", children: jsx(ExperienceTab, { org: tenant, username: username }) }), jsx(TabsContent, { value: "resume", children: jsx(ResumeTab, { org: tenant, username: username }) })] })), activeTab === 'purchases' && jsx(PurchasesTab, { org: tenant, username: username }), activeTab === 'memory' && jsx(MemoryTab, { org: tenant, username: username }), activeTab === 'privacy' && jsx(ChatPrivacyTab, { org: tenant, username: username }), isChatHistoryVisible && activeTab === 'chatHistory' && (jsx(ChatHistoryTab, { org: tenant, username: username })), isLlmUsageVisible && activeTab === 'llmUsage' && (jsx(LlmUsageTab, { org: tenant, username: username, isOwnProfile: !isReadOnly })), !isReadOnly && activeTab === 'security' && (jsx(Security, { app: currentSPA || '', email: (userMetadata === null || userMetadata === void 0 ? void 0 : userMetadata.email) || '', platformKey: tenant, onAccountDeleted: onAccountDeleted })), activeTab === 'advanced' && localLLMProps && (jsx("div", { className: "space-y-6", children: jsx(LocalModelsContent, { isAvailable: localLLMProps.isAvailable, state: localLLMProps.state, ollamaStatus: localLLMProps.ollamaStatus, systemMemory: localLLMProps.systemMemory, isUsingFoundry: localLLMProps.isUsingFoundry, foundryModels: localLLMProps.foundryModels, selectedFoundryModel: localLLMProps.selectedFoundryModel, foundryStatus: localLLMProps.foundryStatus, onStartDownload: localLLMProps.onStartDownload, onCancelDownload: localLLMProps.onCancelDownload, onInstallOllama: localLLMProps.onInstallOllama, onStopManager: localLLMProps.onStopManager, onInstallFoundry: localLLMProps.onInstallFoundry, onCheckStatus: localLLMProps.onCheckStatus, onResetState: localLLMProps.onResetState, onSelectFoundryModel: localLLMProps.onSelectFoundryModel }) }))] }));
274279
+ })] })), activeTab === 'education' && (jsxs(Tabs, { value: educationSubTab, onValueChange: setEducationSubTab, className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxs(TabsList, { children: [jsx(TabsTrigger, { value: "education", children: t('profileIndex.tabEducation') }), jsx(TabsTrigger, { value: "credentials", children: t('gradebookGradebookTab.typeCredentials') }), jsx(TabsTrigger, { value: "skills", children: t('gradebookGradebookTab.typeSkills') })] }), headerAddButton] }), jsx(TabsContent, { value: "education", children: jsx(EducationTab, { org: tenant, username: username }) }), jsx(TabsContent, { value: "credentials", children: jsx(CredentialsList, { org: tenant, username: username }) }), jsx(TabsContent, { value: "skills", children: jsx(SkillsList, { org: tenant, username: username }) })] })), activeTab === 'gradebook' && (jsx(GradebookTab
274280
+ // Remount on a new preselection so the picker starts there.
274281
+ , { org: tenant, username: username, initialType: gradebookType }, gradebookType !== null && gradebookType !== void 0 ? gradebookType : 'courses')), activeTab === 'experience' && (jsxs(Tabs, { value: experienceSubTab, onValueChange: setExperienceSubTab, className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxs(TabsList, { children: [jsx(TabsTrigger, { value: "experience", children: t('profileIndex.tabExperience') }), jsx(TabsTrigger, { value: "resume", children: t('profileIndex.tabResume') })] }), headerAddButton] }), jsx(TabsContent, { value: "experience", children: jsx(ExperienceTab, { org: tenant, username: username }) }), jsx(TabsContent, { value: "resume", children: jsx(ResumeTab, { org: tenant, username: username }) })] })), activeTab === 'purchases' && jsx(PurchasesTab, { org: tenant, username: username }), activeTab === 'memory' && jsx(MemoryTab, { org: tenant, username: username }), activeTab === 'privacy' && jsx(ChatPrivacyTab, { org: tenant, username: username }), isChatHistoryVisible && activeTab === 'chatHistory' && (jsx(ChatHistoryTab, { org: tenant, username: username })), isLlmUsageVisible && activeTab === 'llmUsage' && (jsx(LlmUsageTab, { org: tenant, username: username, isOwnProfile: !isReadOnly })), !isReadOnly && activeTab === 'security' && (jsx(Security, { app: currentSPA || '', email: (userMetadata === null || userMetadata === void 0 ? void 0 : userMetadata.email) || '', platformKey: tenant, onAccountDeleted: onAccountDeleted })), activeTab === 'advanced' && localLLMProps && (jsx("div", { className: "space-y-6", children: jsx(LocalModelsContent, { isAvailable: localLLMProps.isAvailable, state: localLLMProps.state, ollamaStatus: localLLMProps.ollamaStatus, systemMemory: localLLMProps.systemMemory, isUsingFoundry: localLLMProps.isUsingFoundry, foundryModels: localLLMProps.foundryModels, selectedFoundryModel: localLLMProps.selectedFoundryModel, foundryStatus: localLLMProps.foundryStatus, onStartDownload: localLLMProps.onStartDownload, onCancelDownload: localLLMProps.onCancelDownload, onInstallOllama: localLLMProps.onInstallOllama, onStopManager: localLLMProps.onStopManager, onInstallFoundry: localLLMProps.onInstallFoundry, onCheckStatus: localLLMProps.onCheckStatus, onResetState: localLLMProps.onResetState, onSelectFoundryModel: localLLMProps.onSelectFoundryModel }) }))] }));
273291
274282
  }
273292
274283
 
273293
274284
  function CSVEditor({ csvData, onSave, onCancel }) {
@@ -282235,6 +283226,38 @@ const PlatformMembershipContent = ({ platformKey, authURL, }) => {
282235
283226
  return (jsxs("div", { className: "flex items-center justify-between rounded-lg border px-6 py-6", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx("span", { className: "text-sm font-medium text-[#646464]", children: t('advancedPlatformMembership.publicRegistrationLabel') }), jsx(TooltipProvider, { children: jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { "aria-label": t('advancedPlatformMembership.infoAriaLabel'), className: "hidden sm:block", children: jsx(Info$3, { className: "h-4 w-4 text-gray-400" }) }), jsx(TooltipContent, { className: "rounded-lg bg-gray-700 px-3 py-2 text-sm font-medium whitespace-nowrap text-white shadow-sm transition-opacity duration-300 z-50", children: jsx("p", { children: t('advancedPlatformMembership.infoTooltip') }) })] }) }), (membershipData === null || membershipData === void 0 ? void 0 : membershipData.allow_self_linking) && (jsx(TooltipProvider, { children: jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { onClick: handleCopyToClipboard, "aria-label": t('advancedPlatformMembership.copyAriaLabel'), className: "cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800 p-1 rounded transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1", children: jsx(Copy, { className: "h-4 w-4 text-gray-400 hover:text-blue-500" }) }), jsx(TooltipContent, { className: "rounded-lg bg-gray-700 px-3 py-2 text-sm font-medium whitespace-nowrap text-white shadow-sm transition-opacity duration-300 z-50", children: jsx("p", { children: t('advancedPlatformMembership.copyTooltip') }) })] }) }))] }), jsxs("div", { className: "flex items-center gap-2", children: [jsx(Switch, { checked: membershipData === null || membershipData === void 0 ? void 0 : membershipData.allow_self_linking, onCheckedChange: handleToggleMembership, disabled: isUpdating, "aria-label": `${t('advancedPlatformMembership.switchAriaLabel')} ${(membershipData === null || membershipData === void 0 ? void 0 : membershipData.allow_self_linking) ? t('advancedPlatformMembership.switchEnabled') : t('advancedPlatformMembership.switchDisabled')}`, className: "cursor-pointer data-[state=checked]:bg-blue-500" }), isUpdating && (jsx("div", { className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] })] }));
282236
283227
  };
282237
283228
 
283229
+ /**
283230
+ * Toggles the tenant's SEO discoverability (`allow_seo_discoverability`) on the
283231
+ * platform membership config — the same config the public endpoint exposes, so
283232
+ * apps and the sitemap can tell which tenants opted in. Rendered under Public
283233
+ * Registration in the Advanced settings.
283234
+ */
283235
+ const PlatformSeoDiscoverabilityContent = ({ platformKey, }) => {
283236
+ var _a;
283237
+ const t = useT();
283238
+ const [updatePlatformMembership, { isLoading: isUpdating }] = useUpdatePlatformMembershipMutation();
283239
+ const { data: membershipData, isLoading: isLoadingMembership } = useGetPlatformMembershipQuery({
283240
+ platform_key: platformKey,
283241
+ });
283242
+ const handleToggle = async (checked) => {
283243
+ try {
283244
+ await updatePlatformMembership({
283245
+ platform_key: platformKey,
283246
+ allow_seo_discoverability: checked,
283247
+ }).unwrap();
283248
+ toast.success(t('advancedSeoDiscoverability.toastUpdateSuccess'));
283249
+ }
283250
+ catch (error) {
283251
+ console.error(JSON.stringify(error));
283252
+ toast.error(t('advancedSeoDiscoverability.toastUpdateError'));
283253
+ }
283254
+ };
283255
+ if (isLoadingMembership) {
283256
+ return (jsx("div", { className: "rounded-lg border px-6 py-6", style: { borderColor: 'oklch(.922 0 0)' }, children: jsx("div", { className: "animate-pulse", children: jsxs("div", { className: "flex items-center justify-between", children: [jsx("div", { className: "h-4 bg-gray-200 rounded w-1/3" }), jsx("div", { className: "h-6 w-11 bg-gray-200 rounded" })] }) }) }));
283257
+ }
283258
+ return (jsxs("div", { className: "flex items-center justify-between rounded-lg border px-6 py-6", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx("span", { className: "text-sm font-medium text-[#646464]", children: t('advancedSeoDiscoverability.label') }), jsx(TooltipProvider, { children: jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { "aria-label": t('advancedSeoDiscoverability.infoAriaLabel'), className: "hidden sm:block", children: jsx(Info$3, { className: "h-4 w-4 text-gray-400" }) }), jsx(TooltipContent, { className: "rounded-lg bg-gray-700 px-3 py-2 text-sm font-medium text-white shadow-sm transition-opacity duration-300 z-50 max-w-xs", children: jsx("p", { children: t('advancedSeoDiscoverability.infoTooltip') }) })] }) })] }), jsxs("div", { className: "flex items-center gap-2", children: [jsx(Switch, { checked: (_a = membershipData === null || membershipData === void 0 ? void 0 : membershipData.allow_seo_discoverability) !== null && _a !== void 0 ? _a : false, onCheckedChange: handleToggle, disabled: isUpdating, "aria-label": `${t('advancedSeoDiscoverability.switchAriaLabel')} ${(membershipData === null || membershipData === void 0 ? void 0 : membershipData.allow_seo_discoverability) ? t('advancedSeoDiscoverability.switchEnabled') : t('advancedSeoDiscoverability.switchDisabled')}`, className: "cursor-pointer data-[state=checked]:bg-blue-500" }), isUpdating && (jsx("div", { className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] })] }));
283259
+ };
283260
+
282238
283261
  /**
282239
283262
  * Paste-tolerant: a copied address brings a scheme, a path and often a `www.`
282240
283263
  * with it, and a typed one may carry capitals. The backend takes only a
@@ -284476,7 +285499,7 @@ function AdvancedTab({ platformKey, username, currentSPA, authURL, currentPlatfo
284476
285499
  await handleToggleSetting(metadataItem.slug, currentValue);
284477
285500
  }, disabled: isUpdatingTenantMetadata, "aria-label": `${metadataItem.label} ${currentValue ? t('advancedAdvanced.enabled') : t('advancedAdvanced.disabled')}`, className: "cursor-pointer data-[state=checked]:bg-blue-500" }), isUpdatingTenantMetadata && (jsx("div", { className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] })) })] }, metadataItem.slug));
284478
285501
  }) })] }, spa)));
284479
- })()), jsx(StartScreenContent, { platformKey: platformKey, currentSPA: currentSPA }), jsx(ContentViewWrapper, { currentSPA: currentSPA, spas: ['mentor'], children: jsx(ChatAreaWidth, { chatAreaSize: metadata === null || metadata === void 0 ? void 0 : metadata.chat_area_size, isUpdating: isUpdatingTenantMetadata, onUpdate: handleChatAreaSizeUpdate, onError: handleChatAreaSizeError }) }), jsx(AuthSpaCustomizationContent, { platformKey: platformKey, currentSPA: currentSPA }), jsx(AdvancedCssContent, { platformKey: platformKey, currentSPA: currentSPA || '' }), jsx(RecommendationSystemPromptsContent, { platformKey: platformKey, currentSPA: currentSPA }), jsx(StudentMentorCreationContent, { platformKey: platformKey }), jsx(ChatPrivacyContent, { platformKey: platformKey, username: username }), jsx(MemsearchConfigContent, { platformKey: platformKey, userId: username }), jsx(PlatformMembershipContent, { platformKey: platformKey, authURL: authURL }), jsx(CustomDomainsContent, { platformKey: platformKey, username: username, currentSPA: currentSPA || '', currentPlatformBaseDomain: currentPlatformBaseDomain || '' }), jsx(SmtpContent, { platformKey: platformKey }), (currentSPA === null || currentSPA === void 0 ? void 0 : currentSPA.includes('skills')) && (jsxs(Fragment$1, { children: [jsx(ProviderConfigContent, { platformKey: platformKey, username: username }), jsx(ExternalMappingContent, { platformKey: platformKey, username: username })] }))] }) }));
285502
+ })()), jsx(StartScreenContent, { platformKey: platformKey, currentSPA: currentSPA }), jsx(ContentViewWrapper, { currentSPA: currentSPA, spas: ['mentor'], children: jsx(ChatAreaWidth, { chatAreaSize: metadata === null || metadata === void 0 ? void 0 : metadata.chat_area_size, isUpdating: isUpdatingTenantMetadata, onUpdate: handleChatAreaSizeUpdate, onError: handleChatAreaSizeError }) }), jsx(AuthSpaCustomizationContent, { platformKey: platformKey, currentSPA: currentSPA }), jsx(AdvancedCssContent, { platformKey: platformKey, currentSPA: currentSPA || '' }), jsx(RecommendationSystemPromptsContent, { platformKey: platformKey, currentSPA: currentSPA }), jsx(StudentMentorCreationContent, { platformKey: platformKey }), jsx(ChatPrivacyContent, { platformKey: platformKey, username: username }), jsx(MemsearchConfigContent, { platformKey: platformKey, userId: username }), jsx(PlatformMembershipContent, { platformKey: platformKey, authURL: authURL }), jsx(PlatformSeoDiscoverabilityContent, { platformKey: platformKey }), jsx(CustomDomainsContent, { platformKey: platformKey, username: username, currentSPA: currentSPA || '', currentPlatformBaseDomain: currentPlatformBaseDomain || '' }), jsx(SmtpContent, { platformKey: platformKey }), (currentSPA === null || currentSPA === void 0 ? void 0 : currentSPA.includes('skills')) && (jsxs(Fragment$1, { children: [jsx(ProviderConfigContent, { platformKey: platformKey, username: username }), jsx(ExternalMappingContent, { platformKey: platformKey, username: username })] }))] }) }));
284480
285503
  }
284481
285504
 
284482
285505
  function StripeConnect({ platformKey }) {
@@ -295125,7 +296148,7 @@ function Account({ tenant, tenants = [], username, onInviteClick, email, mainPla
295125
296148
  return (jsx(SettingsShell, { sidebarHeader: sidebarHeader, sidebarNav: jsx(SettingsSidebarNav, { groups: navGroups, activeId: activeTab, onSelect: selectTab, variant: "buttons", ariaLabel: t('profileAccount.ariaSettingsNav') }), mobileHeader: mobileHeader, mobileNav: jsx(SettingsMobileNav, { groups: navGroups, activeId: activeTab, onSelect: selectTab, variant: "buttons", ariaLabel: t('profileAccount.ariaSettingsNavMobile') }), title: title, description: description, overlays: jsx(ToastProvider, {}), children: jsxs("div", { className: "space-y-6", children: [activeTab === 'management' && hasManagementPermissions && (jsx(Admin, { onboardingBasePath: onboardingBasePath, authSpaUrl: authURL, onInviteClick: onInviteClick, tenant: tenant, currentSpa: currentSPA, hasUserTabPermission: hasUserTabPermission, hasGroupsTabPermission: hasGroupsTabPermission, hasPoliciesTabPermission: hasPoliciesTabPermission, hasRolesTabPermission: hasRolesTabPermission, hasTeamsTabPermission: hasTeamsTabPermission, hasInviteUserPermission: hasInviteUserPermission, hasCreateTeamPermission: hasCreateTeamPermission, onLoadGroupPermissions: onLoadGroupPermissions, hasAlertsTabPermission: hasAlertsTabPermission, rbacPermissions: rbacPermissions, enableRbac: enableRbac, showGradebookTab: showGradebookTab })), activeTab === 'organization' && (jsx(OrganizationTab, { platformKey: tenant, tenant: tenants.find((ten) => ten.key === tenant), onTenantUpdate: onTenantUpdate, setOrganizationLogoFromOutside: setOrganizationLogo, defaultSupportPhone: defaultSupportPhone, enableSupportPhone: enableSupportPhone })), activeTab === 'integrations' && jsx(IntegrationsTab, { tenantKey: tenant, username: username }), activeTab === 'billing' && canSeeBilling && (jsx(BillingTab, { tenant: tenant, userActiveApp: userActiveApp, username: username, currentUserEmail: email, mainPlatformKey: mainPlatformKey })), activeTab === 'monetization' && jsx(MonetizationTab, { platformKey: tenant, authURL: authURL }), activeTab === 'datasets' && showBenchmarks && (jsx(BenchmarksTab, { tenantKey: tenant, username: username })), activeTab === 'memory' && jsx(MemoryAdminTab, { tenantKey: tenant, username: username }), activeTab === 'virtualMachine' && (jsx(VirtualMachineAdminTab, { tenantKey: tenant, username: username })), activeTab === 'advanced' && (jsx(AdvancedTab, { platformKey: tenant, currentSPA: currentSPA, username: username, authURL: authURL, currentPlatformBaseDomain: currentPlatformBaseDomain }))] }) }));
295126
296149
  }
295127
296150
 
295128
- function UserProfileModal({ isOpen, onClose, params, email, mainPlatformKey, showMentorAIDisplayCheckbox = false, showLeaderboardDisplayCheckbox = false, showGradebookTab = false, showUsernameField = false, showPlatformName = false, useGravatarPicFallback = true, enableCatalogInvite = false, targetTab = 'basic', currentPlan = '', currentSPA = '', userActiveApp = null, authURL, tenants = [], onTenantUpdate, currentPlatformBaseDomain = '', rbacPermissions = {}, enableRbac = false, onLoadGroupPermissions, onTabChange, defaultSupportPhone = '', onBillingTabRequest, onAccountDeleted, enableMemoryTab = false, showLlmUsageTab = true, showBenchmarks = false, localLLMProps, enableSupportPhone, onboardingBasePath = '', }) {
296151
+ function UserProfileModal({ isOpen, onClose, params, email, mainPlatformKey, showMentorAIDisplayCheckbox = false, showLeaderboardDisplayCheckbox = false, showGradebookTab = false, showUsernameField = false, showPlatformName = false, useGravatarPicFallback = true, enableCatalogInvite = false, targetTab = 'basic', currentPlan = '', currentSPA = '', userActiveApp = null, authURL, tenants = [], onTenantUpdate, currentPlatformBaseDomain = '', rbacPermissions = {}, enableRbac = false, onLoadGroupPermissions, onTabChange, defaultSupportPhone = '', onBillingTabRequest, onAccountDeleted, enableMemoryTab = false, showLlmUsageTab = true, showOverviewTab = true, showBenchmarks = false, localLLMProps, enableSupportPhone, onboardingBasePath = '', }) {
295129
296152
  const t = useT();
295130
296153
  console.log('[UserProfileModal] localLLMProps received:', {
295131
296154
  isAvailable: localLLMProps === null || localLLMProps === void 0 ? void 0 : localLLMProps.isAvailable,
@@ -295176,6 +296199,7 @@ function UserProfileModal({ isOpen, onClose, params, email, mainPlatformKey, sho
295176
296199
  onClose();
295177
296200
  }
295178
296201
  }, children: jsxs(DialogContent, { autoFocus: false, forceMount: true, className: "max-w-7xl w-[85vw] p-0 gap-0 overflow-hidden bg-white sm:rounded-2xl profile-component-dialog", style: { height: '85vh', display: 'flex', flexDirection: 'column' }, children: [jsx(DialogTitle, { className: "sr-only", children: t('modalsUserProfileModal.dialogTitle') }), jsx(DialogDescription, { className: "sr-only", children: t('modalsUserProfileModal.dialogDescription') }), [
296202
+ 'overview',
295179
296203
  'basic',
295180
296204
  'social',
295181
296205
  'security',
@@ -295193,7 +296217,7 @@ function UserProfileModal({ isOpen, onClose, params, email, mainPlatformKey, sho
295193
296217
  showPlatformName: showPlatformName,
295194
296218
  useGravatarPicFallback: useGravatarPicFallback,
295195
296219
  showGradebookTab: showGradebookTab,
295196
- }, isAdmin: params.isAdmin, targetTab: targetTab, onClose: onClose, onAccountDeleted: onAccountDeleted, enableMemoryTab: enableMemoryTab, showLlmUsageTab: showLlmUsageTab, localLLMProps: localLLMProps })), [
296220
+ }, isAdmin: params.isAdmin, targetTab: targetTab, onClose: onClose, onAccountDeleted: onAccountDeleted, enableMemoryTab: enableMemoryTab, showLlmUsageTab: showLlmUsageTab, showOverviewTab: showOverviewTab, localLLMProps: localLLMProps })), [
295197
296221
  'organization',
295198
296222
  'management',
295199
296223
  'integrations',