@iblai/iblai-js 2.3.6 → 2.3.7

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$3, useLayoutEffect, createContext, useContext, useMemo, useReducer, useRef, useImperativeHandle, useCallback, isValidElement, Children, PureComponent, cloneElement, Component as Component$1, useId as useId$2, useDebugValue, lazy, Suspense } from 'react';
4
4
  import * as dataLayer from '@iblai/data-layer';
5
- import { useGetUserMetadataQuery, useGetUserMetadataEdxQuery, useUpdateUserMetadataMutation, useUpdateUserMetadataEdxMutation, useUploadProfileImageMutation, useResetPasswordMutation, useSelfRetireMutation, useCreateUserInstitutionMutation, useGetUserInstitutionsQuery, useCreateUserEducationMutation, useUpdateUserEducationMutation, useDeleteUserEducationMutation, useGetUserEducationQuery, useCreateUserCompanyMutation, useGetUserCompaniesQuery, useCreateUserExperienceMutation, useUpdateUserExperienceMutation, useDeleteUserExperienceMutation, useGetUserExperienceQuery, useGetUserResumeQuery, useCreateUserResumeMutation, useGetMySubscriptionsQuery, useGetItemSubscriptionQuery, useCancelSubscriptionMutation, useGetLearnerDetailsQuery, useGetUserEnrolledCoursesQuery, useGetUserEnrolledProgramsQuery, useGetUserCatalogPathwaysQuery, useGetUsersAsAssertionsQuery, useGetUserEarnedSkillsQuery, useGetUserReportedSkillsQuery, useGetUserDesiredSkillsQuery, useCreateGlobalMemoryMutation, useGetMemsearchStatusQuery, useGetUserMemorySettingsQuery, useUpdateUserMemorySettingsMutation, useGetGlobalMemoriesQuery, useGetAllMentorMemoriesQuery, useDeleteGlobalMemoryMutation, useInviteUserMutation, usePlatformInvitationsQuery, useCreateCatalogInvitationCourseBulkMutation, useGetCatalogInvitationsCourseQuery, useLazyPlatformUsersQuery, useLazyPlatformUserGroupsQuery, useGetPersonnalizedSearchQuery, useCreateCatalogInvitationProgramBulkMutation, useGetCatalogInvitationsProgramQuery, 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, useDeleteApiKeyMutation, useGetApiKeyQuery, useGetApiKeyFieldPermissionsQuery, useUpdateApiKeyMutation, useGetApiKeysQuery, unwrapApiTokenList, useCreateApiKeyMutation, useCreateLLMCredentialMutation, useGetCredentialsSchemaQuery, useGetMaskedLLMCredentialsQuery, useGetLlmsQuery, useDeleteIntegrationCredentialMutation, useDeleteCredentialMutation, useCreateIntegrationCredentialMutation, useGetIntegrationCredentialsSchemaQuery, useGetMaskedIntegrationCredentialsQuery, useGetAccountBillingInfoQuery, useUpdateAutoRechargeInfoMutation, useTriggerAutoRechargeMutation, useCreateStripeCustomerPortalMutation, useSetPlatformConfigurationsMutation, useGetPlatformConfigurationsQuery, useUpdatePlatformMembershipMutation, useGetPlatformMembershipQuery, useGetCustomDomainsQuery, useCreateCustomDomainMutation, useDeleteCustomDomainMutation, useGetStudentMentorCreationStatusQuery, useSetStudentMentorCreationStatusMutation, coreApiSlice, recommendationPromptTypeEnum, useGetRecommendedPromptsListQuery, useCreateRecommendedPromptMutation, useUpdateRecommendedPromptMutation, useDeleteRecommendedPromptMutation, useLazyGetPublicPlatformImageAssetFileUrlQuery, useUpdateTenantMetadataMutation, useCreatePlatformImageAssetMutation, useGetProviderConfigQuery, useCreateProviderConfigMutation, useDeleteProviderConfigMutation, useGetExternalMappingQuery, useGetCredentialsListQuery, useCreateExternalMappingMutation, useDeleteExternalMappingMutation, useGetMemsearchConfigQuery, useUpdateMemsearchConfigMutation, useGetStripeConnectStatusQuery, useStartStripeConnectOnboardingMutation, useLazyGetStripeConnectDashboardQuery, useGetAiSearchMentorsQuery, useListPaywallsQuery, useListPricesQuery, useCreatePriceMutation, useUpdatePriceMutation, useDeletePriceMutation, useGetPaywallConfigQuery, useEnablePaywallMutation, useUpdatePaywallMutation, useStarMentorMutation, useUnstarMentorMutation, useLazyGetCourseMetaDataQuery, useLazyGetCourseCompletionOutlinesQuery, useLazyGetCourseEligibilityQuery, useLazyGetEdxSSOTokenQuery, useCreateCourseEnrollmentMutation, useCreateStripeCheckoutSessionMutation, useLazyGetCourseProgressQuery, useLazyGetCourseCompletionQuery, useUpdateExamAttemptMutation, useStartExamMutation, useLazyGetExamInfoQuery, useGetAgentSkillResourcesQuery, useCreateAgentSkillResourceMutation, useUpdateAgentSkillResourceMutation, useUploadAgentSkillResourceAssetMutation, useDeleteAgentSkillResourceMutation, useGetAgentSkillsQuery, useGetMentorSkillAssignmentsQuery, useCreateMentorSkillAssignmentMutation, useUpdateMentorSkillAssignmentMutation, useDeleteMentorSkillAssignmentMutation, useCreateAgentSkillMutation, useUpdateAgentSkillMutation, useDeleteAgentSkillMutation, resolveEffectiveAgentSkills, filterSlashSkills, useUpdateUserProjectMutation, useGetTrainingDocumentsQuery, useGetVectorDocumentsQuery, useGetMentorMemoriesListQuery, useGetMemoryCategoriesAdminQuery, useDeleteMentorMemoryMutation, useUpdateMentorMemoryMutation, useCreateMentorMemoryMutation, 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, useGetMentorGraderConfigurationQuery, useListGraderCriteriaQuery, useCreateMentorGraderConfigurationMutation, useUpdateMentorGraderConfigurationMutation, useCreateGraderCriterionMutation, useUpdateGraderCriterionMutation, useDeleteGraderCriterionMutation, useGetMentorPublicSettingsQuery, useGetChatHistoryFilterQuery, useGetChatHistoryQuery, useGetMentorSummariesQuery, useGetConversationMemoriesQuery, useGetSupportTicketsQuery, useGetSupportTicketMessagesQuery, useCreateSupportTicketMessageMutation, usePatchSupportTicketMutation, useCloseSupportTicketMutation, useCreateLtiMentorMutation, useUpdateLtiMentorMutation, useGetLtiMentorsQuery, 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, useDeletePromptMutation, useDeleteTrainingDocumentMutation, useGetTrainingDocumentRetrainScheduleQuery, useCreateTrainingDocumentRetrainScheduleMutation, useCreateMemoryCategoryMutation, useUpdateMemoryCategoryMutation, useDeleteMemoryCategoryMutation, useUpdateArtifactMutation, useLazyGetArtifactVersionQuery, useLazyListArtifactVersionsQuery, useSetCurrentVersionMutation, useListArtifactVersionsQuery, useLazyGetArtifactQuery, useLazyListArtifactsQuery, useEditSessionMutation } from '@iblai/data-layer';
5
+ import { useGetUserMetadataQuery, useGetUserMetadataEdxQuery, useUpdateUserMetadataMutation, useUpdateUserMetadataEdxMutation, useUploadProfileImageMutation, useResetPasswordMutation, useSelfRetireMutation, useCreateUserInstitutionMutation, useGetUserInstitutionsQuery, useCreateUserEducationMutation, useUpdateUserEducationMutation, useDeleteUserEducationMutation, useGetUserEducationQuery, useCreateUserCompanyMutation, useGetUserCompaniesQuery, useCreateUserExperienceMutation, useUpdateUserExperienceMutation, useDeleteUserExperienceMutation, useGetUserExperienceQuery, useGetUserResumeQuery, useCreateUserResumeMutation, useGetMySubscriptionsQuery, useGetItemSubscriptionQuery, useCancelSubscriptionMutation, useGetLearnerDetailsQuery, useGetUserEnrolledCoursesQuery, useGetUserEnrolledProgramsQuery, useGetUserCatalogPathwaysQuery, useGetUsersAsAssertionsQuery, useGetUserEarnedSkillsQuery, useGetUserReportedSkillsQuery, useGetUserDesiredSkillsQuery, useCreateGlobalMemoryMutation, useGetMemsearchStatusQuery, useGetUserMemorySettingsQuery, useUpdateUserMemorySettingsMutation, useGetGlobalMemoriesQuery, useGetAllMentorMemoriesQuery, useDeleteGlobalMemoryMutation, useInviteUserMutation, usePlatformInvitationsQuery, useCreateCatalogInvitationCourseBulkMutation, useGetCatalogInvitationsCourseQuery, useLazyPlatformUsersQuery, useLazyPlatformUserGroupsQuery, useGetPersonnalizedSearchQuery, useCreateCatalogInvitationProgramBulkMutation, useGetCatalogInvitationsProgramQuery, 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, useDeleteApiKeyMutation, useGetApiKeyQuery, useGetApiKeyFieldPermissionsQuery, useUpdateApiKeyMutation, useGetApiKeysQuery, unwrapApiTokenList, useCreateApiKeyMutation, useCreateLLMCredentialMutation, useGetCredentialsSchemaQuery, useGetMaskedLLMCredentialsQuery, useGetLlmsQuery, useDeleteIntegrationCredentialMutation, useDeleteCredentialMutation, useCreateIntegrationCredentialMutation, useGetIntegrationCredentialsSchemaQuery, useGetMaskedIntegrationCredentialsQuery, useGetAccountBillingInfoQuery, useUpdateAutoRechargeInfoMutation, useTriggerAutoRechargeMutation, useCreateStripeCustomerPortalMutation, useSetPlatformConfigurationsMutation, useGetPlatformConfigurationsQuery, useUpdatePlatformMembershipMutation, useGetPlatformMembershipQuery, useGetCustomDomainsQuery, useCreateCustomDomainMutation, useDeleteCustomDomainMutation, useGetStudentMentorCreationStatusQuery, useSetStudentMentorCreationStatusMutation, coreApiSlice, recommendationPromptTypeEnum, useGetRecommendedPromptsListQuery, useCreateRecommendedPromptMutation, useUpdateRecommendedPromptMutation, useDeleteRecommendedPromptMutation, useLazyGetPublicPlatformImageAssetFileUrlQuery, useUpdateTenantMetadataMutation, useCreatePlatformImageAssetMutation, useGetProviderConfigQuery, useCreateProviderConfigMutation, useDeleteProviderConfigMutation, useGetExternalMappingQuery, useGetCredentialsListQuery, useCreateExternalMappingMutation, useDeleteExternalMappingMutation, useGetMemsearchConfigQuery, useUpdateMemsearchConfigMutation, useGetStripeConnectStatusQuery, useStartStripeConnectOnboardingMutation, useLazyGetStripeConnectDashboardQuery, useGetAiSearchMentorsQuery, useListPaywallsQuery, useListPricesQuery, useCreatePriceMutation, useUpdatePriceMutation, useDeletePriceMutation, useGetPaywallConfigQuery, useEnablePaywallMutation, useUpdatePaywallMutation, useStarMentorMutation, useUnstarMentorMutation, useLazyGetCourseMetaDataQuery, useLazyGetCourseCompletionOutlinesQuery, useLazyGetCourseEligibilityQuery, useLazyGetEdxSSOTokenQuery, useCreateCourseEnrollmentMutation, useCreateStripeCheckoutSessionMutation, useLazyGetCourseProgressQuery, useLazyGetCourseCompletionQuery, useUpdateExamAttemptMutation, useStartExamMutation, useLazyGetExamInfoQuery, useGetAgentSkillResourcesQuery, useCreateAgentSkillResourceMutation, useUpdateAgentSkillResourceMutation, useUploadAgentSkillResourceAssetMutation, useDeleteAgentSkillResourceMutation, useGetAgentSkillsQuery, useGetMentorSkillAssignmentsQuery, useCreateMentorSkillAssignmentMutation, useUpdateMentorSkillAssignmentMutation, useDeleteMentorSkillAssignmentMutation, useCreateAgentSkillMutation, useUpdateAgentSkillMutation, useDeleteAgentSkillMutation, resolveEffectiveAgentSkills, filterSlashSkills, useUpdateUserProjectMutation, useGetTrainingDocumentsQuery, useGetVectorDocumentsQuery, useGetMentorMemoriesListQuery, useGetMemoryCategoriesAdminQuery, useDeleteMentorMemoryMutation, useUpdateMentorMemoryMutation, useCreateMentorMemoryMutation, 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, useGetMentorPublicSettingsQuery, useGetChatHistoryQuery, useGetMentorSummariesQuery, useGetConversationMemoriesQuery, useGetSupportTicketsQuery, useGetSupportTicketMessagesQuery, useCreateSupportTicketMessageMutation, usePatchSupportTicketMutation, useCloseSupportTicketMutation, useCreateLtiMentorMutation, useUpdateLtiMentorMutation, useGetLtiMentorsQuery, 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, useDeletePromptMutation, useDeleteTrainingDocumentMutation, useGetTrainingDocumentRetrainScheduleQuery, useCreateTrainingDocumentRetrainScheduleMutation, useCreateMemoryCategoryMutation, useUpdateMemoryCategoryMutation, useDeleteMemoryCategoryMutation, useUpdateArtifactMutation, useLazyGetArtifactVersionQuery, useLazyListArtifactVersionsQuery, useSetCurrentVersionMutation, useListArtifactVersionsQuery, useLazyGetArtifactQuery, useLazyListArtifactsQuery, useEditSessionMutation } from '@iblai/data-layer';
6
6
  import { getInitials, useTenantMetadata, useCurrentTenant, selectRbacPermissions, isPureWatcher, WithPermissions, canWriteField, useStripeUpgrade, openExternalUrl, CHAT_AREA_SIZE, isAlphaNumeric32, checkRbacPermission, selectNumberOfActiveChatMessages, useUsername, selectStreaming, isLoggedIn, 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, 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';
@@ -102732,11 +102732,12 @@ var graderTabLabels$3 = {
102732
102732
  offHint: "Turn it on to write grading instructions and build your rubric. Anything you set up here is kept safe if you later turn it off."
102733
102733
  },
102734
102734
  subTabs: {
102735
- setup: "Grading setup",
102736
- rubric: "Rubric"
102735
+ setup: "Grading Setup",
102736
+ rubric: "Rubric",
102737
+ results: "Results"
102737
102738
  },
102738
102739
  denied: {
102739
- title: "No access to grading settings",
102740
+ title: "No Access to Grading Settings",
102740
102741
  description: "You don't have permission to view this agent's grading setup. Ask an administrator for access."
102741
102742
  },
102742
102743
  warnings: {
@@ -102744,12 +102745,12 @@ var graderTabLabels$3 = {
102744
102745
  noCriteria: "Grading is on but the rubric is empty — the agent will fail when asked to grade. Add at least one criterion in the Rubric tab."
102745
102746
  },
102746
102747
  config: {
102747
- sectionTitle: "Grading setup",
102748
+ sectionTitle: "Grading Setup",
102748
102749
  gradingMode: {
102749
- label: "What gets graded",
102750
+ label: "What Gets Graded",
102750
102751
  options: {
102751
- submission: "A submission",
102752
- conversation: "The conversation"
102752
+ submission: "A Submission",
102753
+ conversation: "The Conversation"
102753
102754
  },
102754
102755
  help: {
102755
102756
  submission: "The agent grades a piece of work the person hands in, like an essay or answer.",
@@ -102757,16 +102758,16 @@ var graderTabLabels$3 = {
102757
102758
  }
102758
102759
  },
102759
102760
  feedbackMode: {
102760
- label: "Feedback shared with the person",
102761
+ label: "Feedback Shared with the Person",
102761
102762
  options: {
102762
- overall: "Overall feedback only",
102763
- perCriteria: "Feedback per criterion",
102764
- both: "Overall + per criterion"
102763
+ overall: "Overall Feedback Only",
102764
+ perCriteria: "Feedback per Criterion",
102765
+ both: "Overall + per Criterion"
102765
102766
  },
102766
102767
  help: "The overall score is always calculated — this only controls how much detail is shared back."
102767
102768
  },
102768
102769
  instructions: {
102769
- label: "Grading instructions",
102770
+ label: "Grading Instructions",
102770
102771
  placeholder: "Describe what's being graded and anything the grader should know beyond the rubric. E.g. 'You are grading a 500-word persuasive essay on climate policy written by a high-school student. Be encouraging but honest.'",
102771
102772
  help: "Required. This is the context the agent uses every time it grades."
102772
102773
  },
@@ -102778,7 +102779,7 @@ var graderTabLabels$3 = {
102778
102779
  description: "Each row is one thing the agent looks for and how many points it is worth. The overall score is points earned out of the total.",
102779
102780
  needsConfigHint: "Save your grading setup first, then add rubric criteria here.",
102780
102781
  emptyState: "No criteria yet. Add your first one — for example \"Clarity\", 10 points.",
102781
- addButton: "Add criterion",
102782
+ addButton: "Add Criterion",
102782
102783
  columns: {
102783
102784
  name: "Name",
102784
102785
  criteria: "Criteria",
@@ -102787,12 +102788,12 @@ var graderTabLabels$3 = {
102787
102788
  actionsAria: "Actions for {name}",
102788
102789
  edit: "Edit",
102789
102790
  "delete": "Delete",
102790
- totalPoints: "Total possible points: {total}",
102791
+ totalPoints: "Total Possible Points: {total}",
102791
102792
  scoreHint: "Overall score = points earned ÷ {total}.",
102792
102793
  lastCriterionHint: "A rubric needs at least one criterion — add another before removing this one.",
102793
102794
  modal: {
102794
- addTitle: "Add criterion",
102795
- editTitle: "Edit criterion",
102795
+ addTitle: "Add Criterion",
102796
+ editTitle: "Edit Criterion",
102796
102797
  name: {
102797
102798
  label: "Name",
102798
102799
  placeholder: "e.g. Clarity",
@@ -102813,7 +102814,7 @@ var graderTabLabels$3 = {
102813
102814
  cancel: "Cancel"
102814
102815
  },
102815
102816
  deleteModal: {
102816
- title: "Delete criterion",
102817
+ title: "Delete Criterion",
102817
102818
  confirmationPrefix: "Are you sure you want to remove",
102818
102819
  confirmationSuffix: " from the rubric?",
102819
102820
  cancel: "Cancel",
@@ -102831,6 +102832,59 @@ var graderTabLabels$3 = {
102831
102832
  criterionUpdated: "Criterion updated",
102832
102833
  criterionDeleted: "Criterion deleted",
102833
102834
  criterionError: "Couldn't update the rubric"
102835
+ },
102836
+ results: {
102837
+ sectionTitle: "Grade Results",
102838
+ description: "Every grade this agent has issued. Override a score to correct it — the change is pushed back to the LMS the grade came from.",
102839
+ filters: {
102840
+ searchUser: "Search for User",
102841
+ searchUsersPlaceholder: "Search users...",
102842
+ noUsersFound: "No users found.",
102843
+ allUsers: "All Users",
102844
+ statusLabel: "Score Status",
102845
+ allStatuses: "All Statuses",
102846
+ dateRangeLabel: "Pick a Date Range"
102847
+ },
102848
+ statusValues: {
102849
+ pending: "Pending",
102850
+ published: "Published",
102851
+ failed: "Failed"
102852
+ },
102853
+ columns: {
102854
+ learner: "Learner",
102855
+ score: "Score",
102856
+ status: "Status",
102857
+ override: "Override",
102858
+ gradedAt: "Graded"
102859
+ },
102860
+ emptyState: "No grades yet. They will appear here once the agent starts grading.",
102861
+ emptyFiltered: "No grades match the current filters.",
102862
+ overriddenBadge: "Overridden",
102863
+ overrideModal: {
102864
+ title: "Override Grade",
102865
+ learnerLabel: "Learner",
102866
+ aiScoreLabel: "AI Score",
102867
+ currentOverrideLabel: "Current Override",
102868
+ noOverride: "None",
102869
+ pointsLabel: "Override Points",
102870
+ pointsHelp: "Between 0 and {total}. The score pushed to the LMS becomes points ÷ {total}.",
102871
+ pointsRange: "Points must be between 0 and {total}",
102872
+ feedbackLabel: "Override Feedback",
102873
+ feedbackPlaceholder: "Explain the change for the learner (optional).",
102874
+ clearHelp: "Clearing the override restores the AI score and pushes it back to the LMS.",
102875
+ save: "Save",
102876
+ saving: "Saving…",
102877
+ clear: "Clear",
102878
+ clearing: "Clearing…",
102879
+ cancel: "Cancel"
102880
+ },
102881
+ toasts: {
102882
+ overrideSaved: "Override saved and pushed to the LMS",
102883
+ overrideCleared: "Override cleared — the AI score was restored",
102884
+ overrideError: "Couldn't save the override"
102885
+ },
102886
+ overrideButton: "Override",
102887
+ overrideButtonAria: "Override grade for {email}"
102834
102888
  }
102835
102889
  };
102836
102890
  var en = {
@@ -104413,7 +104467,8 @@ var graderTabLabels$2 = {
104413
104467
  },
104414
104468
  subTabs: {
104415
104469
  setup: "Configuration de la notation",
104416
- rubric: "Grille d'évaluation"
104470
+ rubric: "Grille d'évaluation",
104471
+ results: "Résultats"
104417
104472
  },
104418
104473
  denied: {
104419
104474
  title: "Pas d'accès aux paramètres de notation",
@@ -104501,6 +104556,59 @@ var graderTabLabels$2 = {
104501
104556
  deleting: "Suppression…"
104502
104557
  }
104503
104558
  },
104559
+ results: {
104560
+ sectionTitle: "Résultats de notation",
104561
+ description: "Toutes les notes émises par cet agent. Remplacez une note pour la corriger — la modification est renvoyée au LMS d'où provient la note.",
104562
+ filters: {
104563
+ searchUser: "Rechercher un utilisateur",
104564
+ searchUsersPlaceholder: "Rechercher des utilisateurs...",
104565
+ noUsersFound: "Aucun utilisateur trouvé.",
104566
+ allUsers: "Tous les utilisateurs",
104567
+ statusLabel: "Statut de la note",
104568
+ allStatuses: "Tous les statuts",
104569
+ dateRangeLabel: "Choisir une plage de dates"
104570
+ },
104571
+ statusValues: {
104572
+ pending: "En attente",
104573
+ published: "Publié",
104574
+ failed: "Échoué"
104575
+ },
104576
+ columns: {
104577
+ learner: "Apprenant",
104578
+ score: "Note",
104579
+ status: "Statut",
104580
+ override: "Remplacement",
104581
+ gradedAt: "Noté"
104582
+ },
104583
+ emptyState: "Aucune note pour l'instant. Elles apparaîtront ici dès que l'agent commencera à noter.",
104584
+ emptyFiltered: "Aucune note ne correspond aux filtres actuels.",
104585
+ overriddenBadge: "Remplacée",
104586
+ overrideModal: {
104587
+ title: "Remplacer la note",
104588
+ learnerLabel: "Apprenant",
104589
+ aiScoreLabel: "Note de l'IA",
104590
+ currentOverrideLabel: "Remplacement actuel",
104591
+ noOverride: "Aucun",
104592
+ pointsLabel: "Points de remplacement",
104593
+ pointsHelp: "Entre 0 et {total}. La note envoyée au LMS devient points ÷ {total}.",
104594
+ pointsRange: "Les points doivent être compris entre 0 et {total}",
104595
+ feedbackLabel: "Retour sur le remplacement",
104596
+ feedbackPlaceholder: "Expliquez le changement à l'apprenant (facultatif).",
104597
+ clearHelp: "Supprimer le remplacement restaure la note de l'IA et la renvoie au LMS.",
104598
+ save: "Enregistrer",
104599
+ saving: "Enregistrement…",
104600
+ clear: "Supprimer",
104601
+ clearing: "Suppression…",
104602
+ cancel: "Annuler"
104603
+ },
104604
+ toasts: {
104605
+ overrideSaved: "Remplacement enregistré et envoyé au LMS",
104606
+ overrideCleared: "Remplacement supprimé — la note de l'IA a été restaurée",
104607
+ overrideError: "Impossible d'enregistrer le remplacement"
104608
+ },
104609
+ overrideButton: "Remplacer",
104610
+ overrideButtonAria: "Remplacer la note de {email}"
104611
+ },
104504
104612
  toasts: {
104505
104613
  toggleOn: "Notation activée",
104506
104614
  toggleOff: "Notation désactivée — votre grille est conservée pour la prochaine fois",
@@ -110679,7 +110787,8 @@ var graderTabLabels$1 = {
110679
110787
  },
110680
110788
  subTabs: {
110681
110789
  setup: "Configuración de calificación",
110682
- rubric: "Rúbrica"
110790
+ rubric: "Rúbrica",
110791
+ results: "Resultados"
110683
110792
  },
110684
110793
  denied: {
110685
110794
  title: "Sin acceso a la configuración de calificación",
@@ -110767,6 +110876,59 @@ var graderTabLabels$1 = {
110767
110876
  deleting: "Eliminando…"
110768
110877
  }
110769
110878
  },
110879
+ results: {
110880
+ sectionTitle: "Resultados de calificación",
110881
+ description: "Todas las calificaciones que este agente ha emitido. Anula una puntuación para corregirla — el cambio se envía de vuelta al LMS del que proviene la calificación.",
110882
+ filters: {
110883
+ searchUser: "Buscar usuario",
110884
+ searchUsersPlaceholder: "Buscar usuarios...",
110885
+ noUsersFound: "No se encontraron usuarios.",
110886
+ allUsers: "Todos los usuarios",
110887
+ statusLabel: "Estado de la puntuación",
110888
+ allStatuses: "Todos los estados",
110889
+ dateRangeLabel: "Selecciona un rango de fechas"
110890
+ },
110891
+ statusValues: {
110892
+ pending: "Pendiente",
110893
+ published: "Publicado",
110894
+ failed: "Fallido"
110895
+ },
110896
+ columns: {
110897
+ learner: "Estudiante",
110898
+ score: "Puntuación",
110899
+ status: "Estado",
110900
+ override: "Anulación",
110901
+ gradedAt: "Calificado"
110902
+ },
110903
+ emptyState: "Aún no hay calificaciones. Aparecerán aquí cuando el agente comience a calificar.",
110904
+ emptyFiltered: "Ninguna calificación coincide con los filtros actuales.",
110905
+ overriddenBadge: "Anulada",
110906
+ overrideModal: {
110907
+ title: "Anular calificación",
110908
+ learnerLabel: "Estudiante",
110909
+ aiScoreLabel: "Puntuación de la IA",
110910
+ currentOverrideLabel: "Anulación actual",
110911
+ noOverride: "Ninguna",
110912
+ pointsLabel: "Puntos de anulación",
110913
+ pointsHelp: "Entre 0 y {total}. La puntuación enviada al LMS es puntos ÷ {total}.",
110914
+ pointsRange: "Los puntos deben estar entre 0 y {total}",
110915
+ feedbackLabel: "Retroalimentación de la anulación",
110916
+ feedbackPlaceholder: "Explica el cambio al estudiante (opcional).",
110917
+ clearHelp: "Quitar la anulación restaura la puntuación de la IA y la envía de vuelta al LMS.",
110918
+ save: "Guardar",
110919
+ saving: "Guardando…",
110920
+ clear: "Quitar",
110921
+ clearing: "Quitando…",
110922
+ cancel: "Cancelar"
110923
+ },
110924
+ toasts: {
110925
+ overrideSaved: "Anulación guardada y enviada al LMS",
110926
+ overrideCleared: "Anulación quitada — se restauró la puntuación de la IA",
110927
+ overrideError: "No se pudo guardar la anulación"
110928
+ },
110929
+ overrideButton: "Anular",
110930
+ overrideButtonAria: "Anular la calificación de {email}"
110931
+ },
110770
110932
  toasts: {
110771
110933
  toggleOn: "Calificación activada",
110772
110934
  toggleOff: "Calificación desactivada — tu rúbrica se conserva para la próxima vez",
@@ -116945,7 +117107,8 @@ var graderTabLabels = {
116945
117107
  },
116946
117108
  subTabs: {
116947
117109
  setup: "评分设置",
116948
- rubric: "评分标准"
117110
+ rubric: "评分标准",
117111
+ results: "结果"
116949
117112
  },
116950
117113
  denied: {
116951
117114
  title: "无权访问评分设置",
@@ -117033,6 +117196,59 @@ var graderTabLabels = {
117033
117196
  deleting: "删除中…"
117034
117197
  }
117035
117198
  },
117199
+ results: {
117200
+ sectionTitle: "评分结果",
117201
+ description: "此智能体发出的所有评分。覆盖分数即可更正 — 更改会推送回评分来源的 LMS。",
117202
+ filters: {
117203
+ searchUser: "搜索用户",
117204
+ searchUsersPlaceholder: "搜索用户...",
117205
+ noUsersFound: "未找到用户。",
117206
+ allUsers: "所有用户",
117207
+ statusLabel: "分数状态",
117208
+ allStatuses: "全部状态",
117209
+ dateRangeLabel: "选择日期范围"
117210
+ },
117211
+ statusValues: {
117212
+ pending: "待处理",
117213
+ published: "已发布",
117214
+ failed: "失败"
117215
+ },
117216
+ columns: {
117217
+ learner: "学员",
117218
+ score: "分数",
117219
+ status: "状态",
117220
+ override: "覆盖",
117221
+ gradedAt: "评分时间"
117222
+ },
117223
+ emptyState: "还没有评分。智能体开始评分后将显示在这里。",
117224
+ emptyFiltered: "没有符合当前筛选条件的评分。",
117225
+ overriddenBadge: "已覆盖",
117226
+ overrideModal: {
117227
+ title: "覆盖评分",
117228
+ learnerLabel: "学员",
117229
+ aiScoreLabel: "AI 分数",
117230
+ currentOverrideLabel: "当前覆盖",
117231
+ noOverride: "无",
117232
+ pointsLabel: "覆盖分数",
117233
+ pointsHelp: "介于 0 和 {total} 之间。推送到 LMS 的分数为 分数 ÷ {total}。",
117234
+ pointsRange: "分数必须介于 0 和 {total} 之间",
117235
+ feedbackLabel: "覆盖反馈",
117236
+ feedbackPlaceholder: "向学员说明此更改(可选)。",
117237
+ clearHelp: "清除覆盖会恢复 AI 分数并推送回 LMS。",
117238
+ save: "保存",
117239
+ saving: "保存中…",
117240
+ clear: "清除",
117241
+ clearing: "清除中…",
117242
+ cancel: "取消"
117243
+ },
117244
+ toasts: {
117245
+ overrideSaved: "覆盖已保存并推送到 LMS",
117246
+ overrideCleared: "覆盖已清除 — AI 分数已恢复",
117247
+ overrideError: "无法保存覆盖"
117248
+ },
117249
+ overrideButton: "覆盖",
117250
+ overrideButtonAria: "覆盖 {email} 的评分"
117251
+ },
117036
117252
  toasts: {
117037
117253
  toggleOn: "评分已开启",
117038
117254
  toggleOff: "评分已关闭 — 您的评分标准已保留,下次可继续使用",
@@ -175814,7 +176030,7 @@ function DetailRow({ label, children }) {
175814
176030
  return (jsxs("div", { className: "flex items-center justify-between gap-4 py-2", children: [jsx("span", { className: "text-sm text-gray-500", children: label }), jsx("span", { className: "text-sm font-medium text-gray-900 text-right", children: children })] }));
175815
176031
  }
175816
176032
 
175817
- const PAGE_SIZE$a = 8;
176033
+ const PAGE_SIZE$b = 8;
175818
176034
  const CONTENT_TYPES = [
175819
176035
  { value: 'courses', labelKey: 'gradebookGradebookTab.typeCourses', icon: GraduationCap },
175820
176036
  { value: 'programs', labelKey: 'gradebookGradebookTab.typePrograms', icon: Layers },
@@ -175845,14 +176061,14 @@ function useGradebookData(type, org, username, page, search) {
175845
176061
  username,
175846
176062
  query: {
175847
176063
  page,
175848
- page_size: PAGE_SIZE$a,
176064
+ page_size: PAGE_SIZE$b,
175849
176065
  platform_key: org,
175850
176066
  ...(trimmed ? { search: trimmed } : {}),
175851
176067
  },
175852
176068
  }, { skip: type !== 'courses', refetchOnMountOrArgChange: true });
175853
176069
  const programsQ = useGetUserEnrolledProgramsQuery([{ username, platformKey: org }], { skip: type !== 'programs' });
175854
176070
  const pathwaysQ = useGetUserCatalogPathwaysQuery({ username, platform_key: org }, { skip: type !== 'pathways' });
175855
- const credentialsQ = useGetUsersAsAssertionsQuery({ platformKey: org, userId: username, page, pageSize: PAGE_SIZE$a }, { skip: type !== 'credentials', refetchOnMountOrArgChange: true });
176071
+ const credentialsQ = useGetUsersAsAssertionsQuery({ platformKey: org, userId: username, page, pageSize: PAGE_SIZE$b }, { skip: type !== 'credentials', refetchOnMountOrArgChange: true });
175856
176072
  const earnedQ = useGetUserEarnedSkillsQuery([{ org, userId: username }], { skip: type !== 'skills' });
175857
176073
  const reportedQ = useGetUserReportedSkillsQuery([{ username }], { skip: type !== 'skills' });
175858
176074
  const desiredQ = useGetUserDesiredSkillsQuery([{ username }], { skip: type !== 'skills' });
@@ -175862,12 +176078,12 @@ function useGradebookData(type, org, username, page, search) {
175862
176078
  const filtered = trimmed
175863
176079
  ? rows.filter((row) => row.name.toLowerCase().includes(trimmed.toLowerCase()))
175864
176080
  : rows;
175865
- const start = (page - 1) * PAGE_SIZE$a;
176081
+ const start = (page - 1) * PAGE_SIZE$b;
175866
176082
  return {
175867
- rows: filtered.slice(start, start + PAGE_SIZE$a),
176083
+ rows: filtered.slice(start, start + PAGE_SIZE$b),
175868
176084
  total: filtered.length,
175869
176085
  hasPrev: page > 1,
175870
- hasNext: start + PAGE_SIZE$a < filtered.length,
176086
+ hasNext: start + PAGE_SIZE$b < filtered.length,
175871
176087
  };
175872
176088
  };
175873
176089
  switch (type) {
@@ -175924,7 +176140,7 @@ function useGradebookData(type, org, username, page, search) {
175924
176140
  rows,
175925
176141
  total,
175926
176142
  hasPrev: page > 1,
175927
- hasNext: page * PAGE_SIZE$a < total,
176143
+ hasNext: page * PAGE_SIZE$b < total,
175928
176144
  isLoading: credentialsQ.isLoading,
175929
176145
  isFetching: credentialsQ.isFetching,
175930
176146
  isError: credentialsQ.isError,
@@ -178408,7 +178624,7 @@ const PopoverContent = React.forwardRef(({ className, align = 'center', sideOffs
178408
178624
  });
178409
178625
  PopoverContent.displayName = Content2$2.displayName;
178410
178626
 
178411
- const PAGE_SIZE$9 = 10;
178627
+ const PAGE_SIZE$a = 10;
178412
178628
  function UsersTab({ tenant, onInviteClick, currentSpa, showGradebookTab = false, }) {
178413
178629
  var _a, _b;
178414
178630
  const t = useT();
@@ -178430,7 +178646,7 @@ function UsersTab({ tenant, onInviteClick, currentSpa, showGradebookTab = false,
178430
178646
  const isWatcher = isPureWatcher(rbacPermissions, currentTenant);
178431
178647
  const { data: users, refetch: refetchPlatformUsers, isLoading: isLoadingPlatformUsers, } = usePlatformUsersQuery({
178432
178648
  page,
178433
- page_size: PAGE_SIZE$9,
178649
+ page_size: PAGE_SIZE$a,
178434
178650
  platform_key: tenant,
178435
178651
  platform_org: tenant,
178436
178652
  query: debouncedSearchQuery,
@@ -178444,7 +178660,7 @@ function UsersTab({ tenant, onInviteClick, currentSpa, showGradebookTab = false,
178444
178660
  // TODO to use required_action: 'Ibl.Core/Users/read',
178445
178661
  required_action: 'Ibl.Mentor/Memory/list',
178446
178662
  page,
178447
- page_size: PAGE_SIZE$9,
178663
+ page_size: PAGE_SIZE$a,
178448
178664
  sort: 'name',
178449
178665
  ...(debouncedSearchQuery.includes('@')
178450
178666
  ? { email: debouncedSearchQuery }
@@ -178613,7 +178829,7 @@ function UsersTab({ tenant, onInviteClick, currentSpa, showGradebookTab = false,
178613
178829
  managed: user,
178614
178830
  }));
178615
178831
  const totalCount = (_b = (isWatcher ? accessibleUsers === null || accessibleUsers === void 0 ? void 0 : accessibleUsers.count : users === null || users === void 0 ? void 0 : users.count)) !== null && _b !== void 0 ? _b : 0;
178616
- const totalPages = Math.ceil(totalCount / PAGE_SIZE$9);
178832
+ const totalPages = Math.ceil(totalCount / PAGE_SIZE$a);
178617
178833
  return (jsxs("div", { className: "mt-4", children: [jsxs("div", { className: "flex justify-between items-center gap-1", children: [jsxs("div", { className: "relative mb-6 max-w-sm", children: [jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { type: "text", value: searchQuery, onChange: (event) => setQuerySearch(event.target.value), placeholder: t('tabsUserstab.searchPlaceholder'), className: "pl-10 pr-10 focus:ring-blue-500 focus:border-blue-500 h-[35px]", "aria-label": t('tabsUserstab.searchAriaLabel') }), searchQuery.length > 0 && (searchQuery !== debouncedSearchQuery || isLoading) && (jsx(LoaderCircle, { "data-testid": "search-spinner", className: "absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400 animate-spin", "aria-hidden": "true" }))] }), !isWatcher && (jsx("div", { className: "mb-6", children: jsx(Button$1, { className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] hover:opacity-90 text-white h-[35px]", onClick: onInviteClick, children: t('tabsUserstab.inviteButton') }) }))] }), isLoading ? (jsx("div", { className: "flex justify-center items-center h-64", children: jsx(Spinner, {}) })) : (jsxs(Fragment$1, { children: [jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: `px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 ${isWatcher ? 'w-[40%]' : 'w-[16%]'}`, children: t('tabsUserstab.columnName') }), jsx("th", { className: `px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 ${isWatcher ? 'w-[60%]' : 'w-[25%]'}`, children: t('tabsUserstab.columnEmail') }), !isWatcher && (jsxs(Fragment$1, { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[16%]", children: t('tabsUserstab.columnRole') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[25%]", children: t('tabsUserstab.columnPolicies') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[18%]", children: t('tabsUserstab.columnStatus') })] }))] }) }), jsxs("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: [rows.map((row) => {
178618
178834
  // Only set on the admin path — see {@link UserRow}.
178619
178835
  const user = row.managed;
@@ -178639,7 +178855,7 @@ function UsersTab({ tenant, onInviteClick, currentSpa, showGradebookTab = false,
178639
178855
  })] }) })] }) }), jsx("td", { className: "px-6 py-4", onClick: (e) => e.stopPropagation(), children: jsx(Switch, { checked: user.active, onCheckedChange: (checked) => handleUserStatusChange(user, checked), disabled: updatingUserIds.has(user === null || user === void 0 ? void 0 : user.user_id), "aria-label": t('tabsUserstab.toggleStatusAriaLabel', {
178640
178856
  name: user.name,
178641
178857
  }), className: "cursor-pointer data-[state=checked]:bg-blue-500 disabled:cursor-not-allowed disabled:opacity-50" }) })] }))] }, row.key));
178642
- }), rows.length === 0 && (jsx("tr", { children: jsx("td", { colSpan: isWatcher ? 2 : 5, className: "px-6 py-8 text-center text-gray-500 dark:text-gray-400", children: t('tabsUserstab.noUsersFound') }) }))] })] }) }), jsx(AdvancedPagination, { variant: "footer", className: "-mx-6 -mb-6 mt-4 rounded-b-lg", totalPages: totalPages, currentPage: page, onPageChange: (_page) => handlePageChange(_page), totalCount: totalCount, itemsPerPage: PAGE_SIZE$9, itemLabel: "users" })] })), selectedUser && (jsx(Dialog, { open: !!selectedUser, onOpenChange: (open) => {
178858
+ }), rows.length === 0 && (jsx("tr", { children: jsx("td", { colSpan: isWatcher ? 2 : 5, className: "px-6 py-8 text-center text-gray-500 dark:text-gray-400", children: t('tabsUserstab.noUsersFound') }) }))] })] }) }), jsx(AdvancedPagination, { variant: "footer", className: "-mx-6 -mb-6 mt-4 rounded-b-lg", totalPages: totalPages, currentPage: page, onPageChange: (_page) => handlePageChange(_page), totalCount: totalCount, itemsPerPage: PAGE_SIZE$a, itemLabel: "users" })] })), selectedUser && (jsx(Dialog, { open: !!selectedUser, onOpenChange: (open) => {
178643
178859
  if (!open)
178644
178860
  setSelectedUser(null);
178645
178861
  }, children: jsxs(DialogContent, { autoFocus: false, className: "max-w-7xl w-[85vw] p-0 gap-0 overflow-hidden bg-white profile-component-dialog", style: { height: '85vh', display: 'flex', flexDirection: 'column' }, children: [jsx(DialogTitle, { className: "sr-only", children: t('tabsUserstab.profileDialogTitle') }), jsx(DialogDescription, { className: "sr-only", children: t('tabsUserstab.profileDialogDescription') }), jsx(Profile, { tenant: tenant, tenants: [], username: selectedUser.username, isAdmin: selectedUser.isAdmin, currentSPA: currentSpa, onClose: () => setSelectedUser(null), customization: {
@@ -179859,7 +180075,7 @@ function PoliciesTab({ tenant }) {
179859
180075
  : t('tabsPoliciestab.createPolicy')] }) }) }), editing && (policyDetails === null || policyDetails === void 0 ? void 0 : policyDetails.is_internal) && (jsx(TooltipContent, { children: jsx("p", { children: t('tabsPoliciestab.cannotEditInternal') }) }))] }) })] })] }) }), jsx(ResourcePickerModal, { open: isResourcePickerOpen, onOpenChange: setIsResourcePickerOpen, tenant: tenant, onSelect: addPickedResource })] }));
179860
180076
  }
179861
180077
 
179862
- const PAGE_SIZE$8 = 10;
180078
+ const PAGE_SIZE$9 = 10;
179863
180079
  function normalizeEvents(events) {
179864
180080
  if (!events)
179865
180081
  return [];
@@ -179908,8 +180124,8 @@ function AlertsTab({ tenant }) {
179908
180124
  const { data: watchedGroupsData, isLoading, isError, refetch, } = useGetWatchedGroupsQuery({
179909
180125
  params: {
179910
180126
  platform_key: tenant,
179911
- limit: PAGE_SIZE$8,
179912
- offset: (page - 1) * PAGE_SIZE$8,
180127
+ limit: PAGE_SIZE$9,
180128
+ offset: (page - 1) * PAGE_SIZE$9,
179913
180129
  },
179914
180130
  });
179915
180131
  const groups = useMemo(() => {
@@ -179922,7 +180138,7 @@ function AlertsTab({ tenant }) {
179922
180138
  return results;
179923
180139
  }, [watchedGroupsData, debouncedSearchQuery]);
179924
180140
  const totalPages = watchedGroupsData
179925
- ? Math.max(1, Math.ceil(watchedGroupsData.count / PAGE_SIZE$8))
180141
+ ? Math.max(1, Math.ceil(watchedGroupsData.count / PAGE_SIZE$9))
179926
180142
  : 0;
179927
180143
  const handlePageChange = async (newPage) => {
179928
180144
  setPage(newPage);
@@ -180231,7 +180447,7 @@ function AlertsTab({ tenant }) {
180231
180447
  setDeletingGroupId(null);
180232
180448
  }
180233
180449
  }
180234
- return (jsxs("div", { className: "mt-4", children: [jsxs("div", { className: "flex mb-6 gap-2 flex-row items-center justify-between", children: [jsxs("div", { className: "relative max-w-sm w-full sm:w-auto", children: [jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), placeholder: t('tabsAlertstab.searchAlertsPlaceholder'), "aria-label": t('tabsAlertstab.searchAlertsAriaLabel'), className: "pl-10 pr-10 focus:ring-blue-500 focus:border-blue-500 h-[35px]" }), isLoading && (jsx(LoaderCircle, { "data-testid": "search-spinner", className: "absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400 animate-spin", "aria-hidden": "true" }))] }), jsx("div", { className: "flex gap-2", children: jsx(Button$1, { onClick: openNew, "aria-label": t('tabsAlertstab.newAlertAriaLabel'), className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] hover:opacity-90 text-white h-[35px]", children: t('tabsAlertstab.newAlert') }) })] }), isLoading && (jsx("div", { className: "flex justify-center items-center h-64", children: jsx("div", { className: "py-8 text-center text-sm text-gray-500 dark:text-gray-400", children: t('tabsAlertstab.loading') }) })), isError && (jsx("div", { className: "py-8 text-center text-sm text-red-500", children: t('tabsAlertstab.failedToLoadAlerts') })), !isLoading && !isError && (jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400", children: t('tabsAlertstab.columnName') }), jsx("th", { className: "px-6 py-3 text-right font-medium text-gray-500 dark:text-gray-400 w-[120px]" })] }) }), jsxs("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: [groups.map((g) => (jsxs("tr", { children: [jsx("td", { className: "px-6 py-4 text-gray-900 dark:text-gray-100 text-sm", children: g.name }), jsx("td", { className: "px-6 py-4", children: jsxs("div", { className: "flex gap-2 justify-end", children: [jsx(Button$1, { variant: "ghost", size: "sm", onClick: () => openEdit(g), disabled: deletingGroupId === g.id, "aria-label": t('tabsAlertstab.editAlertAriaLabel', { name: g.name }), children: jsx(Pencil, { className: "h-4 w-4", "aria-hidden": "true" }) }), jsx(Button$1, { variant: "ghost", size: "sm", onClick: () => onDelete(g), className: "text-red-600 hover:text-red-700", disabled: deletingGroupId === g.id, "aria-label": t('tabsAlertstab.deleteAlertAriaLabel', { name: g.name }), children: deletingGroupId === g.id ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin", "aria-hidden": "true" })) : (jsx(Trash2, { className: "h-4 w-4", "aria-hidden": "true" })) })] }) })] }, g.id))), groups.length === 0 && (jsx("tr", { children: jsx("td", { colSpan: 2, className: "px-6 py-8 text-center text-gray-500 dark:text-gray-400", children: t('tabsAlertstab.noAlertsFound') }) }))] })] }) })), !isLoading && !isError && (jsx(AdvancedPagination, { variant: "footer", className: "-mx-6 -mb-6 mt-4 rounded-b-lg", totalPages: totalPages, currentPage: page, onPageChange: (newPage) => handlePageChange(newPage), totalCount: watchedGroupsData === null || watchedGroupsData === void 0 ? void 0 : watchedGroupsData.count, itemsPerPage: PAGE_SIZE$8, itemLabel: "alerts" })), jsx(Dialog, { open: isOpen, onOpenChange: setIsOpen, children: jsxs(DialogContent, { "aria-describedby": undefined, className: "max-w-2xl max-h-[90vh] overflow-y-auto", children: [jsx(DialogHeader, { children: jsx(DialogTitle, { children: editingGroup ? t('tabsAlertstab.editAlert') : t('tabsAlertstab.newAlert') }) }), jsxs("div", { className: "space-y-5", children: [jsxs("div", { className: "grid gap-1.5", children: [jsx(Label$1, { htmlFor: "wg-name", children: t('tabsAlertstab.nameLabel') }), jsx(Input, { id: "wg-name", value: name, onChange: (e) => setName(e.target.value), placeholder: t('tabsAlertstab.enterAlertNamePlaceholder'), required: true })] }), jsxs("div", { className: "grid gap-1.5", children: [jsx(Label$1, { children: t('tabsAlertstab.watchedUsersLabel') }), jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: t('tabsAlertstab.watchedUsersDescription') }), watchedUsers.length > 0 ? (jsx("div", { className: "space-y-2 max-h-48 overflow-y-auto border border-gray-200 dark:border-gray-700 rounded-md p-2", children: watchedUsers.map((user) => (jsxs("div", { className: "flex items-center justify-between bg-gray-50 dark:bg-gray-800 p-2 rounded-md", children: [jsxs("div", { className: "flex flex-col", children: [jsx("span", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: user.name || user.username }), user.email && (jsx("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: user.email }))] }), jsx(Button$1, { type: "button", variant: "ghost", size: "sm", onClick: () => removeWatchedUserDraft(user.id), className: "h-8 w-8 p-0 text-red-600 hover:text-red-700 hover:bg-red-50 dark:hover:bg-red-900/20", "aria-label": t('tabsAlertstab.removeWatchedUserAriaLabel', {
180450
+ return (jsxs("div", { className: "mt-4", children: [jsxs("div", { className: "flex mb-6 gap-2 flex-row items-center justify-between", children: [jsxs("div", { className: "relative max-w-sm w-full sm:w-auto", children: [jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), placeholder: t('tabsAlertstab.searchAlertsPlaceholder'), "aria-label": t('tabsAlertstab.searchAlertsAriaLabel'), className: "pl-10 pr-10 focus:ring-blue-500 focus:border-blue-500 h-[35px]" }), isLoading && (jsx(LoaderCircle, { "data-testid": "search-spinner", className: "absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400 animate-spin", "aria-hidden": "true" }))] }), jsx("div", { className: "flex gap-2", children: jsx(Button$1, { onClick: openNew, "aria-label": t('tabsAlertstab.newAlertAriaLabel'), className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] hover:opacity-90 text-white h-[35px]", children: t('tabsAlertstab.newAlert') }) })] }), isLoading && (jsx("div", { className: "flex justify-center items-center h-64", children: jsx("div", { className: "py-8 text-center text-sm text-gray-500 dark:text-gray-400", children: t('tabsAlertstab.loading') }) })), isError && (jsx("div", { className: "py-8 text-center text-sm text-red-500", children: t('tabsAlertstab.failedToLoadAlerts') })), !isLoading && !isError && (jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400", children: t('tabsAlertstab.columnName') }), jsx("th", { className: "px-6 py-3 text-right font-medium text-gray-500 dark:text-gray-400 w-[120px]" })] }) }), jsxs("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: [groups.map((g) => (jsxs("tr", { children: [jsx("td", { className: "px-6 py-4 text-gray-900 dark:text-gray-100 text-sm", children: g.name }), jsx("td", { className: "px-6 py-4", children: jsxs("div", { className: "flex gap-2 justify-end", children: [jsx(Button$1, { variant: "ghost", size: "sm", onClick: () => openEdit(g), disabled: deletingGroupId === g.id, "aria-label": t('tabsAlertstab.editAlertAriaLabel', { name: g.name }), children: jsx(Pencil, { className: "h-4 w-4", "aria-hidden": "true" }) }), jsx(Button$1, { variant: "ghost", size: "sm", onClick: () => onDelete(g), className: "text-red-600 hover:text-red-700", disabled: deletingGroupId === g.id, "aria-label": t('tabsAlertstab.deleteAlertAriaLabel', { name: g.name }), children: deletingGroupId === g.id ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin", "aria-hidden": "true" })) : (jsx(Trash2, { className: "h-4 w-4", "aria-hidden": "true" })) })] }) })] }, g.id))), groups.length === 0 && (jsx("tr", { children: jsx("td", { colSpan: 2, className: "px-6 py-8 text-center text-gray-500 dark:text-gray-400", children: t('tabsAlertstab.noAlertsFound') }) }))] })] }) })), !isLoading && !isError && (jsx(AdvancedPagination, { variant: "footer", className: "-mx-6 -mb-6 mt-4 rounded-b-lg", totalPages: totalPages, currentPage: page, onPageChange: (newPage) => handlePageChange(newPage), totalCount: watchedGroupsData === null || watchedGroupsData === void 0 ? void 0 : watchedGroupsData.count, itemsPerPage: PAGE_SIZE$9, itemLabel: "alerts" })), jsx(Dialog, { open: isOpen, onOpenChange: setIsOpen, children: jsxs(DialogContent, { "aria-describedby": undefined, className: "max-w-2xl max-h-[90vh] overflow-y-auto", children: [jsx(DialogHeader, { children: jsx(DialogTitle, { children: editingGroup ? t('tabsAlertstab.editAlert') : t('tabsAlertstab.newAlert') }) }), jsxs("div", { className: "space-y-5", children: [jsxs("div", { className: "grid gap-1.5", children: [jsx(Label$1, { htmlFor: "wg-name", children: t('tabsAlertstab.nameLabel') }), jsx(Input, { id: "wg-name", value: name, onChange: (e) => setName(e.target.value), placeholder: t('tabsAlertstab.enterAlertNamePlaceholder'), required: true })] }), jsxs("div", { className: "grid gap-1.5", children: [jsx(Label$1, { children: t('tabsAlertstab.watchedUsersLabel') }), jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: t('tabsAlertstab.watchedUsersDescription') }), watchedUsers.length > 0 ? (jsx("div", { className: "space-y-2 max-h-48 overflow-y-auto border border-gray-200 dark:border-gray-700 rounded-md p-2", children: watchedUsers.map((user) => (jsxs("div", { className: "flex items-center justify-between bg-gray-50 dark:bg-gray-800 p-2 rounded-md", children: [jsxs("div", { className: "flex flex-col", children: [jsx("span", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: user.name || user.username }), user.email && (jsx("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: user.email }))] }), jsx(Button$1, { type: "button", variant: "ghost", size: "sm", onClick: () => removeWatchedUserDraft(user.id), className: "h-8 w-8 p-0 text-red-600 hover:text-red-700 hover:bg-red-50 dark:hover:bg-red-900/20", "aria-label": t('tabsAlertstab.removeWatchedUserAriaLabel', {
180235
180451
  username: user.username,
180236
180452
  }), children: jsx(X$2, { className: "h-4 w-4" }) })] }, user.id))) })) : (jsx("div", { className: "text-sm text-gray-500 dark:text-gray-400 p-4 text-center border border-dashed border-gray-300 dark:border-gray-600 rounded-md", children: t('tabsAlertstab.noWatchedUsersAdded') })), jsxs("div", { className: "relative", children: [jsx(Input, { value: watchedUserSearch, onChange: (e) => {
180237
180453
  setWatchedUserSearch(e.target.value);
@@ -181551,7 +181767,7 @@ function BlocksView({ platformKey, onBack, }) {
181551
181767
  }
181552
181768
 
181553
181769
  const FILTER_ORDER = ['all', ...APPLICATION_STATUSES];
181554
- const PAGE_SIZE$7 = 20;
181770
+ const PAGE_SIZE$8 = 20;
181555
181771
  const SEARCH_DEBOUNCE_MS = 300;
181556
181772
  /**
181557
181773
  * The public application URL on the auth SPA for one form of a platform
@@ -181684,7 +181900,7 @@ function SubmissionsPipeline({ platformKey, form, onBack, onOpen, }) {
181684
181900
  ...(sort !== '-created' ? { sort } : {}),
181685
181901
  ...candidateParams,
181686
181902
  page,
181687
- page_size: PAGE_SIZE$7,
181903
+ page_size: PAGE_SIZE$8,
181688
181904
  }, {
181689
181905
  refetchOnMountOrArgChange: true,
181690
181906
  });
@@ -181693,7 +181909,7 @@ function SubmissionsPipeline({ platformKey, form, onBack, onOpen, }) {
181693
181909
  : [];
181694
181910
  const rows = form ? allRows.filter((row) => row.form_id === form.id) : allRows;
181695
181911
  const count = typeof (pipeline === null || pipeline === void 0 ? void 0 : pipeline.count) === 'number' ? pipeline.count : allRows.length;
181696
- const totalPages = Math.max(1, Math.ceil(count / PAGE_SIZE$7));
181912
+ const totalPages = Math.max(1, Math.ceil(count / PAGE_SIZE$8));
181697
181913
  const counts = statsCounts(stats);
181698
181914
  const countFor = (key) => {
181699
181915
  if (!stats)
@@ -181731,7 +181947,7 @@ function SubmissionsPipeline({ platformKey, form, onBack, onOpen, }) {
181731
181947
  }) }) }), jsx("td", { className: "whitespace-nowrap px-6 py-4 text-sm text-gray-600 dark:text-gray-300", children: formatDate(row) }), jsx("td", { className: "px-6 py-4", children: jsx(Badge, { variant: "outline", className: approvalTone(row.status), children: STATUS_LABEL_KEYS[row.status]
181732
181948
  ? t(STATUS_LABEL_KEYS[row.status])
181733
181949
  : row.status }) })] }, row.id));
181734
- })) })] }) }), jsx(AdvancedPagination, { variant: "footer", className: "-mx-6 -mb-6 mt-4 rounded-b-lg", totalPages: totalPages, currentPage: page, onPageChange: (newPage) => setPage(newPage), totalCount: count, itemsPerPage: PAGE_SIZE$7, itemLabel: "applications" })] }))] }));
181950
+ })) })] }) }), jsx(AdvancedPagination, { variant: "footer", className: "-mx-6 -mb-6 mt-4 rounded-b-lg", totalPages: totalPages, currentPage: page, onPageChange: (newPage) => setPage(newPage), totalCount: count, itemsPerPage: PAGE_SIZE$8, itemLabel: "applications" })] }))] }));
181735
181951
  }
181736
181952
 
181737
181953
  const TabDescription = ({ icon, title, children }) => {
@@ -186723,6 +186939,64 @@ function CreateApiModal$1({ isOpen, onClose, tenantKey, username }) {
186723
186939
  : t('apiTabLabels.createModal.submit') })) }) })] })] }) }), apiKey && jsx(ApiKeyModal$1, { isOpen: true, onClose: () => setApiKey(null), apiKey: apiKey })] }));
186724
186940
  }
186725
186941
 
186942
+ /**
186943
+ * Returns the canonical logo path and display name for an LLM provider.
186944
+ * `logo` is a static-root path (e.g. `/llm-amazon-provider.png`); the package
186945
+ * ships the canonical assets under `@iblai/web-containers/public/` — copy them
186946
+ * into your app's static-root (`public/` for Next.js) so the paths resolve.
186947
+ */
186948
+ function getLLMProviderDetails(llmProvider, llmName) {
186949
+ switch (llmProvider) {
186950
+ case 'groq':
186951
+ return { logo: '/llm-groq-provider.png', name: 'Groq' };
186952
+ case 'azure_openai':
186953
+ return { logo: '/llm-microsoft-provider.png', name: 'Microsoft' };
186954
+ case 'openai':
186955
+ if (llmName)
186956
+ return { logo: '/llm-openai-provider.jpg', name: 'OpenAI' };
186957
+ return { logo: '/llm-openai-provider-2.svg', name: 'OpenAI' };
186958
+ case 'mistral':
186959
+ return { logo: '/llm-mistral-provider.jpeg', name: 'Mistral' };
186960
+ case 'google':
186961
+ if (llmName)
186962
+ return { logo: '/llm-gemini-provider.png', name: 'Google' };
186963
+ return { logo: '/llm-google-provider.svg', name: 'Google' };
186964
+ case 'llama':
186965
+ return { logo: '/llm-llama-provider.jpeg', name: 'Meta' };
186966
+ case 'perplexity':
186967
+ return { logo: '/llm-perplexity-provider.webp', name: 'Perplexity' };
186968
+ case 'deepseek':
186969
+ return { logo: '/llm-deepseek-provider.png', name: 'DeepSeek' };
186970
+ case 'xai':
186971
+ return { logo: '/llm-xai-provider.jpg', name: 'xAI' };
186972
+ case 'IBLChatAnthropic':
186973
+ case 'anthropic':
186974
+ return { logo: '/llm-claude-provider.png', name: 'Anthropic' };
186975
+ case 'IBLChatNvidia':
186976
+ case 'nvidia':
186977
+ return { logo: '/llm-nvidia-provider.webp', name: 'NVIDIA' };
186978
+ case 'bedrock':
186979
+ case 'amazon-bedrock':
186980
+ case 'amazon_bedrock':
186981
+ case 'IBLChatBedrock':
186982
+ return { logo: '/llm-amazon-provider.png', name: 'Amazon' };
186983
+ // ibl.ai's own hosted provider. The backend key is `iblai` (NameEnum.IBLAI);
186984
+ // the other cases cover the `IBLChat<Vendor>` house spelling and the
186985
+ // dotted/dashed/underscored brand forms seen in labels and older payloads.
186986
+ case 'iblai':
186987
+ case 'IBLAI':
186988
+ case 'ibl.ai':
186989
+ case 'ibl_ai':
186990
+ case 'ibl-ai':
186991
+ case 'ibl':
186992
+ case 'IBLChatIBL':
186993
+ case 'IBLChatIBLAI':
186994
+ return { logo: '/llm-iblai-provider.png', name: 'ibl.ai' };
186995
+ default:
186996
+ return { logo: '/llm-generic-provider.png', name: llmProvider };
186997
+ }
186998
+ }
186999
+
186726
187000
  // Dynamic schema based on selected provider
186727
187001
  const createDynamicSchema$1 = (schemaFields) => {
186728
187002
  const schemaObj = {
@@ -186951,10 +187225,14 @@ function CreateLLMModal({ isOpen, onClose, tenantKey, onSuccess }) {
186951
187225
  }
186952
187226
  }, children: [jsx(SelectTrigger, { children: jsx(SelectValue, { placeholder: t('llmsTabCreateLlmModal.selectProviderPlaceholder') }) }), jsx(SelectContent, { children: availableProviders.map((provider) => {
186953
187227
  var _a, _b;
186954
- const providerLogo = (_a = provider === null || provider === void 0 ? void 0 : provider.service_info) === null || _a === void 0 ? void 0 : _a.logo;
187228
+ // Prefer the logo the API ships; fall back to the
187229
+ // bundled provider artwork so known providers (ibl.ai
187230
+ // included) never degrade to a generic key emoji.
187231
+ const providerLogo = ((_a = provider === null || provider === void 0 ? void 0 : provider.service_info) === null || _a === void 0 ? void 0 : _a.logo) ||
187232
+ getLLMProviderDetails(provider.name).logo;
186955
187233
  const providerName = ((_b = provider === null || provider === void 0 ? void 0 : provider.service_info) === null || _b === void 0 ? void 0 : _b.display_name) ||
186956
187234
  provider.name;
186957
- return (jsx(SelectItem, { value: provider.name, children: jsxs("div", { className: "flex items-center gap-2", children: [providerLogo ? (jsx("img", { src: providerLogo, alt: provider.name, className: "w-4 h-4 rounded-sm object-contain" })) : (jsx("span", { children: "\uD83D\uDD11" })), providerName || provider.name] }) }, provider.name));
187235
+ return (jsx(SelectItem, { value: provider.name, children: jsxs("div", { className: "flex items-center gap-2", children: [jsx("img", { src: providerLogo, alt: provider.name, className: "w-4 h-4 rounded-sm object-contain" }), providerName || provider.name] }) }, provider.name));
186958
187236
  }) })] }), shouldShowError && (jsx("p", { className: "text-red-500 text-xs", children: (_b = field.state.meta.errors[0]) === null || _b === void 0 ? void 0 : _b.message }))] }));
186959
187237
  } })), isCredentialsSchemaLoading && (jsxs("div", { className: "flex items-center justify-center py-4", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin mr-2" }), jsx("span", { className: "text-sm text-gray-600", children: t('llmsTabCreateLlmModal.loadingProviderConfigurations') })] })), showProviderForm && !isCredentialsSchemaLoading && !isAzureOpenAI && (jsx(Fragment$1, { children: schemaFields.map((fieldName) => (jsx(form.Field, { name: fieldName, children: (field) => {
186960
187238
  var _a, _b;
@@ -187043,17 +187321,22 @@ function IntegrationLLMsTab({ tenantKey }) {
187043
187321
  return (jsxs("div", { className: "space-y-4", children: [jsx(InfoBanner, { icon: jsx(Bot, { className: "w-5 h-5" }), children: t('llmsTabIntegrationLlmsTab.infoBannerText') }), jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsxs("table", { className: "w-full text-sm min-w-[600px]", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400", children: t('llmsTabIntegrationLlmsTab.colName') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400", children: t('llmsTabIntegrationLlmsTab.colKey') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[50px]" })] }) }), jsx("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: isMaskedCredentialsLoading ? (jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-8 text-center text-sm text-gray-500", children: t('llmsTabIntegrationLlmsTab.loading') }) })) : maskedCredentials.length === 0 ? (jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-8 text-center text-sm text-gray-500", children: t('llmsTabIntegrationLlmsTab.noLlmKeysFound') }) })) : (maskedCredentials.map((cred, idx) => {
187044
187322
  var _a, _b, _c;
187045
187323
  const provider = ((_a = cred.service_info) === null || _a === void 0 ? void 0 : _a.display_name) || cred.name;
187046
- // Use logo from service_info only
187324
+ // Prefer the logo the API ships; fall back to the bundled
187325
+ // provider artwork so known providers (ibl.ai included) never
187326
+ // degrade to a generic key emoji.
187047
187327
  let logoUrl;
187048
187328
  let logoAlt;
187049
187329
  if ((_b = cred.service_info) === null || _b === void 0 ? void 0 : _b.logo) {
187050
187330
  logoUrl = cred.service_info.logo;
187051
187331
  logoAlt = cred.service_info.display_name || cred.service_info.name;
187052
187332
  }
187333
+ else {
187334
+ logoUrl = getLLMProviderDetails(cred.name).logo;
187335
+ }
187053
187336
  const isAzure = isAzureOpenAI(cred);
187054
187337
  const azureModels = isAzure ? getAzureModels(cred) : [];
187055
187338
  const isExpanded = expandedRows.has(cred.name);
187056
- return (jsxs(React__default.Fragment, { children: [jsxs("tr", { children: [jsx("td", { className: "px-6 py-4", children: jsxs("div", { className: "flex items-center gap-2", children: [logoUrl ? (jsx("img", { src: logoUrl, alt: logoAlt || provider || cred.name, className: "w-6 h-6 rounded-sm object-contain" })) : (jsx("span", { className: "text-lg", children: '🔑' })), jsx("span", { className: "font-normal text-gray-900 dark:text-gray-100", children: provider || cred.name }), isAzure && azureModels.length > 0 && (jsx("button", { type: "button", onClick: () => toggleRowExpansion(cred.name), className: "p-0.5 hover:bg-gray-100 rounded", children: isExpanded ? (jsx(ChevronUp, { className: "h-4 w-4 text-gray-500" })) : (jsx(ChevronDown, { className: "h-4 w-4 text-gray-500" })) }))] }) }), jsx("td", { className: "px-6 py-4 font-mono text-sm text-gray-900 dark:text-gray-100", children: isAzure ? (jsx("span", { className: "text-xs text-gray-500", children: t('llmsTabIntegrationLlmsTab.azureModelCount', {
187339
+ return (jsxs(React__default.Fragment, { children: [jsxs("tr", { children: [jsx("td", { className: "px-6 py-4", children: jsxs("div", { className: "flex items-center gap-2", children: [jsx("img", { src: logoUrl, alt: logoAlt || provider || cred.name, className: "w-6 h-6 rounded-sm object-contain" }), jsx("span", { className: "font-normal text-gray-900 dark:text-gray-100", children: provider || cred.name }), isAzure && azureModels.length > 0 && (jsx("button", { type: "button", onClick: () => toggleRowExpansion(cred.name), className: "p-0.5 hover:bg-gray-100 rounded", children: isExpanded ? (jsx(ChevronUp, { className: "h-4 w-4 text-gray-500" })) : (jsx(ChevronDown, { className: "h-4 w-4 text-gray-500" })) }))] }) }), jsx("td", { className: "px-6 py-4 font-mono text-sm text-gray-900 dark:text-gray-100", children: isAzure ? (jsx("span", { className: "text-xs text-gray-500", children: t('llmsTabIntegrationLlmsTab.azureModelCount', {
187057
187340
  count: azureModels.length,
187058
187341
  }) })) : (String((_c = cred === null || cred === void 0 ? void 0 : cred.value) === null || _c === void 0 ? void 0 : _c.key).slice(0, 15) || '') }), jsx("td", { className: "px-6 py-4", children: jsx(Button$1, { variant: "ghost", size: "sm", className: "cursor-pointer mr-2", disabled: isDeletingIntegration || isDeletingCredential, onClick: () => handleDeleteCredential(cred.name, cred.platform, false), children: jsx(Trash, { className: "h-4 w-4" }) }) })] }), isAzure &&
187059
187342
  isExpanded &&
@@ -189819,7 +190102,7 @@ function ItemSearchDropdown({ platformKey, onSelect, }) {
189819
190102
  }, children: [jsx("div", { className: "flex-1 min-w-0", children: jsx("span", { className: "text-sm font-medium text-gray-900 dark:text-gray-100 block truncate", children: item.name }) }), jsx(Badge, { variant: "secondary", className: "text-xs shrink-0 capitalize", children: displayItemType(item.itemType) })] }, `${item.itemType}-${item.id}`)))) : isFetching ? (jsx("div", { className: "px-3 py-4 text-center text-sm text-gray-400", children: t('monetizationItemSearchDropdown.searching') })) : (jsx("div", { className: "px-3 py-4 text-center text-sm text-gray-400", children: t('monetizationItemSearchDropdown.noItemsFound') })) }))] }));
189820
190103
  }
189821
190104
 
189822
- const PAGE_SIZE$6 = 8;
190105
+ const PAGE_SIZE$7 = 8;
189823
190106
  function PaywalledItemsList({ platformKey, onSelectItem, onAddCustomItem, }) {
189824
190107
  const t = useT();
189825
190108
  const [page, setPage] = useState(1);
@@ -189827,7 +190110,7 @@ function PaywalledItemsList({ platformKey, onSelectItem, onAddCustomItem, }) {
189827
190110
  const { data: paywalls, isLoading } = useListPaywallsQuery({
189828
190111
  platform_key: platformKey,
189829
190112
  page,
189830
- page_size: PAGE_SIZE$6,
190113
+ page_size: PAGE_SIZE$7,
189831
190114
  ...(statusFilter !== 'all' && { is_enabled: statusFilter === 'active' }),
189832
190115
  }, { refetchOnMountOrArgChange: true });
189833
190116
  return (jsxs("div", { className: "space-y-4", children: [jsx(Card, { className: "shadow-sm border", style: { borderColor: 'oklch(.922 0 0)' }, children: jsxs(CardContent, { className: "p-4", children: [jsx("h4", { className: "text-sm font-medium text-gray-700 dark:text-gray-300 mb-3", children: t('monetizationPaywalledItemsList.configureItemForSale') }), jsxs("div", { className: "flex items-center gap-2", children: [jsx(ItemSearchDropdown, { platformKey: platformKey, onSelect: (itemType, uniqueId, name) => onSelectItem(itemType, uniqueId, name) }), jsx(Button$1, { variant: "outline", size: "icon", onClick: onAddCustomItem, className: "shrink-0 cursor-pointer", title: t('monetizationPaywalledItemsList.addCustomItemTitle'), children: jsx(Plus, { className: "h-4 w-4" }) })] })] }) }), jsxs("div", { className: "space-y-2", children: [jsxs("div", { className: "flex items-center justify-between", children: [jsx("h4", { className: "text-sm font-medium text-gray-500", children: t('monetizationPaywalledItemsList.configuredItems') }), jsxs(Select$1, { value: statusFilter, onValueChange: (v) => {
@@ -189850,7 +190133,7 @@ function PaywalledItemsList({ platformKey, onSelectItem, onAddCustomItem, }) {
189850
190133
  : 'bg-gray-100 text-gray-500 border-gray-200 hover:bg-gray-100', children: pw.is_enabled
189851
190134
  ? t('monetizationPaywalledItemsList.statusActive')
189852
190135
  : t('monetizationPaywalledItemsList.statusDisabled') })] }) }, `${pw.item_type}-${pw.item_id}`));
189853
- }), jsx(AdvancedPagination, { variant: "footer", className: "mt-2 rounded-lg border", currentPage: page, totalPages: Math.ceil(paywalls.count / PAGE_SIZE$6), onPageChange: setPage, totalCount: paywalls.count, itemsPerPage: PAGE_SIZE$6, itemLabel: "items" })] })) : (jsx("p", { className: "text-sm text-gray-400 text-center py-6", children: statusFilter !== 'all'
190136
+ }), jsx(AdvancedPagination, { variant: "footer", className: "mt-2 rounded-lg border", currentPage: page, totalPages: Math.ceil(paywalls.count / PAGE_SIZE$7), onPageChange: setPage, totalCount: paywalls.count, itemsPerPage: PAGE_SIZE$7, itemLabel: "items" })] })) : (jsx("p", { className: "text-sm text-gray-400 text-center py-6", children: statusFilter !== 'all'
189854
190137
  ? t('monetizationPaywalledItemsList.noFilteredItemsFound', { status: statusFilter })
189855
190138
  : t('monetizationPaywalledItemsList.noItemsConfigured') }))] })] }));
189856
190139
  }
@@ -253554,52 +253837,6 @@ var reactPaginate = {exports: {}};
253554
253837
 
253555
253838
  } (reactPaginate));
253556
253839
 
253557
- /**
253558
- * Returns the canonical logo path and display name for an LLM provider.
253559
- * `logo` is a static-root path (e.g. `/llm-amazon-provider.png`); the package
253560
- * ships the canonical assets under `@iblai/web-containers/public/` — copy them
253561
- * into your app's static-root (`public/` for Next.js) so the paths resolve.
253562
- */
253563
- function getLLMProviderDetails(llmProvider, llmName) {
253564
- switch (llmProvider) {
253565
- case 'groq':
253566
- return { logo: '/llm-groq-provider.png', name: 'Groq' };
253567
- case 'azure_openai':
253568
- return { logo: '/llm-microsoft-provider.png', name: 'Microsoft' };
253569
- case 'openai':
253570
- if (llmName)
253571
- return { logo: '/llm-openai-provider.jpg', name: 'OpenAI' };
253572
- return { logo: '/llm-openai-provider-2.svg', name: 'OpenAI' };
253573
- case 'mistral':
253574
- return { logo: '/llm-mistral-provider.jpeg', name: 'Mistral' };
253575
- case 'google':
253576
- if (llmName)
253577
- return { logo: '/llm-gemini-provider.png', name: 'Google' };
253578
- return { logo: '/llm-google-provider.svg', name: 'Google' };
253579
- case 'llama':
253580
- return { logo: '/llm-llama-provider.jpeg', name: 'Meta' };
253581
- case 'perplexity':
253582
- return { logo: '/llm-perplexity-provider.webp', name: 'Perplexity' };
253583
- case 'deepseek':
253584
- return { logo: '/llm-deepseek-provider.png', name: 'DeepSeek' };
253585
- case 'xai':
253586
- return { logo: '/llm-xai-provider.jpg', name: 'xAI' };
253587
- case 'IBLChatAnthropic':
253588
- case 'anthropic':
253589
- return { logo: '/llm-claude-provider.png', name: 'Anthropic' };
253590
- case 'IBLChatNvidia':
253591
- case 'nvidia':
253592
- return { logo: '/llm-nvidia-provider.webp', name: 'NVIDIA' };
253593
- case 'bedrock':
253594
- case 'amazon-bedrock':
253595
- case 'amazon_bedrock':
253596
- case 'IBLChatBedrock':
253597
- return { logo: '/llm-amazon-provider.png', name: 'Amazon' };
253598
- default:
253599
- return { logo: '/llm-generic-provider.png', name: llmProvider };
253600
- }
253601
- }
253602
-
253603
253840
  function OverlayModal({ open, onClose, title, description, className, children, }) {
253604
253841
  const t = useT();
253605
253842
  const [mounted, setMounted] = useState(false);
@@ -254972,7 +255209,7 @@ function RetrievedDocumentsButton({ sessionId }) {
254972
255209
  return (jsxs(Fragment$1, { children: [jsxs(Button$1, { variant: "outline", size: "sm", className: "flex items-center gap-2 border-gray-200 bg-white text-gray-700 hover:bg-gray-50", onClick: () => setIsOpen(true), children: [jsx(FileText, { className: "h-4 w-4 text-blue-600" }), jsx("span", { children: t('retrievedDocumentsButton.title') })] }), jsx(Dialog, { open: isOpen, onOpenChange: setIsOpen, children: jsxs(DialogContent, { className: "flex max-h-[80vh] flex-col gap-0 p-0 sm:max-w-[425px] md:max-w-[600px]", children: [jsx(DialogHeader, { className: "border-b px-4 py-2", children: jsxs(DialogTitle, { className: "flex items-center gap-2 text-base font-medium text-[#646464]", children: [jsx(FileText, { className: "h-5 w-5 text-blue-600" }), t('retrievedDocumentsButton.title')] }) }), jsx("div", { className: "flex-1 overflow-hidden", children: jsx(DocumentSidebar, { isModal: true, sessionId: sessionId }) })] }) })] }));
254973
255210
  }
254974
255211
 
254975
- const PAGE_SIZE$5 = 10;
255212
+ const PAGE_SIZE$6 = 10;
254976
255213
  const MemoryMenu = ({ onClose, mentorId, tenantKey, username }) => {
254977
255214
  const t = useT();
254978
255215
  const [page, setPage] = useState(1);
@@ -254990,7 +255227,7 @@ const MemoryMenu = ({ onClose, mentorId, tenantKey, username }) => {
254990
255227
  mentorId,
254991
255228
  params: {
254992
255229
  page,
254993
- page_size: PAGE_SIZE$5,
255230
+ page_size: PAGE_SIZE$6,
254994
255231
  my_memory: true,
254995
255232
  },
254996
255233
  }, {
@@ -258849,7 +259086,7 @@ function DeleteItemConfirm({ isOpen, onClose, tenantKey, username, datasetName,
258849
259086
  : t('benchmarksDeleteItemConfirm.delete') })] })] }) }));
258850
259087
  }
258851
259088
 
258852
- const PAGE_SIZE$4 = 10;
259089
+ const PAGE_SIZE$5 = 10;
258853
259090
  function BenchmarkItemsModal({ isOpen, onClose, tenantKey, username, datasetName }) {
258854
259091
  var _a;
258855
259092
  const t = useT();
@@ -258861,17 +259098,17 @@ function BenchmarkItemsModal({ isOpen, onClose, tenantKey, username, datasetName
258861
259098
  userId: username,
258862
259099
  datasetName,
258863
259100
  page,
258864
- limit: PAGE_SIZE$4,
259101
+ limit: PAGE_SIZE$5,
258865
259102
  });
258866
259103
  const items = (_a = data === null || data === void 0 ? void 0 : data.results) !== null && _a !== void 0 ? _a : [];
258867
- const totalPages = evalTotalPages(data === null || data === void 0 ? void 0 : data.count, PAGE_SIZE$4);
259104
+ const totalPages = evalTotalPages(data === null || data === void 0 ? void 0 : data.count, PAGE_SIZE$5);
258868
259105
  return (jsx(Dialog, { open: isOpen, onOpenChange: (open) => !open && onClose(), children: jsxs(DialogContent, { "aria-label": "benchmark-items", className: "w-full max-w-4xl max-h-[90vh] overflow-y-auto", children: [jsxs(DialogHeader, { children: [jsx(DialogTitle, { children: datasetName }), jsx(DialogDescription, { children: t('benchmarksBenchmarkItemsModal.description') })] }), jsx("div", { className: "flex justify-end mb-4", children: jsxs(Button$1, { onClick: () => setShowAdd(true), className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] hover:opacity-90 text-white h-[35px]", children: [jsx(Plus, { className: "h-4 w-4 mr-1" }), t('benchmarksBenchmarkItemsModal.addItems')] }) }), isLoading ? (jsx("div", { className: "flex justify-center items-center h-40", children: jsx(Spinner, {}) })) : (jsxs(Fragment$1, { children: [jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-4 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[45%]", children: t('benchmarksBenchmarkItemsModal.questionColumn') }), jsx("th", { className: "px-4 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[45%]", children: t('benchmarksBenchmarkItemsModal.answerColumn') }), jsx("th", { className: "px-4 py-3 text-right font-medium text-gray-500 dark:text-gray-400 w-[10%]", children: t('benchmarksBenchmarkItemsModal.actionsColumn') })] }) }), jsxs("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: [items.map((item) => {
258869
259106
  var _a;
258870
259107
  return (jsxs("tr", { className: "align-top", children: [jsx("td", { className: "px-4 py-3 text-gray-900 dark:text-gray-100", children: jsx("div", { className: "line-clamp-3 break-words", children: typeof item.input === 'string' ? item.input : JSON.stringify(item.input) }) }), jsx("td", { className: "px-4 py-3 text-gray-600 dark:text-gray-300", children: jsx("div", { className: "line-clamp-3 break-words", children: (_a = item.expected_output) !== null && _a !== void 0 ? _a : jsx("span", { className: "text-gray-400", children: "\u2014" }) }) }), jsx("td", { className: "px-4 py-3 text-right", children: jsx(Button$1, { variant: "ghost", size: "sm", "aria-label": t('benchmarksBenchmarkItemsModal.deleteItemAriaLabel'), onClick: () => setDeleteItemId(item.id), children: jsx(Trash2, { className: "h-4 w-4 text-red-500" }) }) })] }, item.id));
258871
259108
  }), items.length === 0 && (jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-4 py-8 text-center text-gray-500 dark:text-gray-400", children: t('benchmarksBenchmarkItemsModal.empty') }) }))] })] }) }), totalPages > 1 && (jsx("div", { className: "mt-6", children: jsx(AdvancedPagination, { totalPages: totalPages, currentPage: page, onPageChange: setPage }) }))] })), jsx(AddItemsModal, { isOpen: showAdd, onClose: () => setShowAdd(false), tenantKey: tenantKey, username: username, datasetName: datasetName }), deleteItemId && (jsx(DeleteItemConfirm, { isOpen: !!deleteItemId, onClose: () => setDeleteItemId(null), tenantKey: tenantKey, username: username, datasetName: datasetName, itemId: deleteItemId }))] }) }));
258872
259109
  }
258873
259110
 
258874
- const PAGE_SIZE$3 = 10;
259111
+ const PAGE_SIZE$4 = 10;
258875
259112
  function BenchmarksTab({ tenantKey, username, }) {
258876
259113
  var _a;
258877
259114
  const t = useT();
@@ -258883,13 +259120,13 @@ function BenchmarksTab({ tenantKey, username, }) {
258883
259120
  org: tenantKey,
258884
259121
  userId: username,
258885
259122
  page,
258886
- limit: PAGE_SIZE$3,
259123
+ limit: PAGE_SIZE$4,
258887
259124
  });
258888
259125
  const benchmarks = (_a = data === null || data === void 0 ? void 0 : data.results) !== null && _a !== void 0 ? _a : [];
258889
259126
  const filtered = searchQuery.trim()
258890
259127
  ? benchmarks.filter((benchmark) => benchmark.name.toLowerCase().includes(searchQuery.toLowerCase()))
258891
259128
  : benchmarks;
258892
- const totalPages = evalTotalPages(data === null || data === void 0 ? void 0 : data.count, PAGE_SIZE$3);
259129
+ const totalPages = evalTotalPages(data === null || data === void 0 ? void 0 : data.count, PAGE_SIZE$4);
258893
259130
  return (jsxs("div", { className: "mt-4", children: [jsxs("div", { className: "flex justify-between items-center gap-1 flex-wrap", children: [jsxs("div", { className: "relative mb-6 max-w-sm w-full sm:w-auto", children: [jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { type: "text", value: searchQuery, onChange: (event) => setSearchQuery(event.target.value), placeholder: t('benchmarksIndex.searchPlaceholder'), className: "pl-10 pr-10 focus:ring-blue-500 focus:border-blue-500 h-[35px]", "aria-label": t('benchmarksIndex.searchAriaLabel') })] }), jsx("div", { className: "mb-6", children: jsxs(Button$1, { className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] hover:opacity-90 text-white h-[35px]", onClick: () => setShowCreate(true), children: [jsx(Plus, { className: "h-4 w-4 mr-1" }), t('benchmarksIndex.newBenchmark')] }) })] }), isLoading ? (jsx("div", { className: "flex justify-center items-center h-64", children: jsx(Spinner, {}) })) : (jsxs(Fragment$1, { children: [jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[28%]", children: t('benchmarksIndex.nameColumn') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[36%]", children: t('benchmarksIndex.descriptionColumn') }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[20%]", children: t('benchmarksIndex.createdColumn') }), jsx("th", { className: "px-6 py-3 text-right font-medium text-gray-500 dark:text-gray-400 w-[16%]", children: t('benchmarksIndex.actionsColumn') })] }) }), jsxs("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: [filtered.map((benchmark) => (jsxs("tr", { children: [jsx("td", { className: "px-6 py-4 text-gray-900 dark:text-gray-100 max-w-0", children: jsx("div", { className: "truncate font-medium", children: benchmark.name }) }), jsx("td", { className: "px-6 py-4 text-gray-600 dark:text-gray-300 max-w-0", children: jsx("div", { className: "truncate", children: benchmark.description || '—' }) }), jsx("td", { className: "px-6 py-4 text-gray-600 dark:text-gray-300 whitespace-nowrap", children: benchmark.created_at
258894
259131
  ? formatDistanceToNow(new Date(benchmark.created_at), {
258895
259132
  addSuffix: true,
@@ -264745,8 +264982,74 @@ function canSwitchProvider(providers, name) {
264745
264982
  const provider = providers.find((p) => p.name === name);
264746
264983
  return !!(provider === null || provider === void 0 ? void 0 : provider.chat_models) && provider.chat_models.length > 0;
264747
264984
  }
264985
+ /**
264986
+ * Whether we hold a usable LLM key for this provider — its own credentials, or
264987
+ * the tenant's main keys when it is allowed to borrow them. An *absent*
264988
+ * `main_has_credentials` means the backend did not report on the main keys and
264989
+ * is treated as available (matching standalone's `@/lib/utils` and
264990
+ * `claw-sandbox`'s copy); only an explicit `false` rules the main keys out.
264991
+ */
264748
264992
  function canSwitchLLm(llm) {
264749
- return !!(llm === null || llm === void 0 ? void 0 : llm.has_credentials) || (!!(llm === null || llm === void 0 ? void 0 : llm.can_use_main_keys) && !!(llm === null || llm === void 0 ? void 0 : llm.main_has_credentials));
264993
+ if (llm === null || llm === void 0 ? void 0 : llm.has_credentials) {
264994
+ return true;
264995
+ }
264996
+ return ((llm === null || llm === void 0 ? void 0 : llm.can_use_main_keys) &&
264997
+ ((llm === null || llm === void 0 ? void 0 : llm.main_has_credentials) === true || (llm === null || llm === void 0 ? void 0 : llm.main_has_credentials) === undefined));
264998
+ }
264999
+ /**
265000
+ * Compares two raw provider names by the label the user actually sees on the
265001
+ * card, not by the backend key — the two diverge often enough to matter
265002
+ * (`bedrock` renders as "Amazon", `azure_openai` as "Microsoft", `iblai` as
265003
+ * "ibl.ai"). Comparison is case-insensitive (`sensitivity: 'base'`) so casing
265004
+ * never produces a surprising order. `getDetails` is the host-provided resolver
265005
+ * the grid renders with, so the sort always matches what is on screen; unknown
265006
+ * providers fall back to their raw name as the display name.
265007
+ */
265008
+ function compareLLMProvidersByDisplayName(a, b, getDetails) {
265009
+ return getDetails(a).name.localeCompare(getDetails(b).name, undefined, {
265010
+ sensitivity: 'base',
265011
+ });
265012
+ }
265013
+ /**
265014
+ * Whether the user can reach *any* model of this provider.
265015
+ *
265016
+ * This is exactly the provider-level half of the per-model `isDisabled` rule in
265017
+ * `llm-tab/llm-provider-modal.tsx`: a model row there is disabled when
265018
+ * `!canSwitchLLm(provider) || !canSwitchProvider(llms, provider.name)`, and both
265019
+ * of those depend only on the provider — so when either fails, *every* model row
265020
+ * of that provider is disabled. `canSwitchProvider` is just "has at least one
265021
+ * `chat_models` entry", which is checked inline here to keep the helper pure and
265022
+ * free of the surrounding provider list.
265023
+ *
265024
+ * `canSwitchLLm` can return `undefined` (its `can_use_main_keys` branch), hence
265025
+ * the explicit `Boolean(...)`.
265026
+ */
265027
+ function canAccessProvider(provider) {
265028
+ var _a, _b;
265029
+ return Boolean(canSwitchLLm(provider !== null && provider !== void 0 ? provider : {})) && ((_b = (_a = provider === null || provider === void 0 ? void 0 : provider.chat_models) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0;
265030
+ }
265031
+ /**
265032
+ * Orders LLM provider cards as two alphabetical groups: providers the user can
265033
+ * actually use (see {@link canAccessProvider}) first, then the ones they can't —
265034
+ * each group sorted alphabetically by display name.
265035
+ *
265036
+ * The grouping predicate is deliberately the same one the grid grays cards with,
265037
+ * so the two always line up: group 1 renders normally, group 2 renders grayed.
265038
+ * Grouping on credentials alone would let a provider that has a key but ships no
265039
+ * chat models sort into the "usable" group while rendering grayed.
265040
+ *
265041
+ * Pure and non-mutating: RTK Query results are frozen, so the input is copied
265042
+ * before sorting. `Array.prototype.sort` is stable, so providers that tie on
265043
+ * both group and display name keep their original relative order.
265044
+ */
265045
+ function sortLLMProvidersByCredentials(providers, getDetails) {
265046
+ return [...providers].sort((a, b) => {
265047
+ const aUsable = canAccessProvider(a);
265048
+ const bUsable = canAccessProvider(b);
265049
+ if (aUsable !== bUsable)
265050
+ return aUsable ? -1 : 1;
265051
+ return compareLLMProvidersByDisplayName(a.name, b.name, getDetails);
265052
+ });
264750
265053
  }
264751
265054
  function extractErrorMessage(error, fallback) {
264752
265055
  var _a, _b;
@@ -264817,12 +265120,16 @@ function LLMProviderModal({ isOpen, onClose, onSelect, llmProvider, isSelecting,
264817
265120
  return (jsxs("button", { disabled: isDisabled, onClick: () => {
264818
265121
  onSelect(llmProvider.name, llm.llm_name);
264819
265122
  }, className: cn('flex cursor-pointer items-center gap-3 rounded-lg border border-gray-200 p-4 transition-colors', {
264820
- 'cursor-not-allowed border-gray-200 bg-white': isDisabled,
265123
+ // Matches the provider grid's inactive treatment: tinted
265124
+ // card, faded logo, full-strength label.
265125
+ 'cursor-not-allowed border-gray-100 bg-gray-50': isDisabled && !isActive,
264821
265126
  'hover:border-blue-500 hover:bg-blue-50': !isDisabled,
264822
265127
  'cursor-not-allowed border-blue-500 bg-blue-50': isActive,
264823
265128
  }), children: [jsx("span", { className: "flex h-8 w-8 items-center justify-center overflow-hidden rounded-lg", children: jsx(Image$4, { src: providerDetails.logo, alt: `${providerDetails.name} icon`, className: cn('h-full w-full object-contain', {
264824
- grayscale: isDisabled && !isActive,
264825
- }), width: 32, height: 32, loading: "lazy" }) }), jsx("span", { className: "text-left text-sm font-medium text-[#646464]", children: llm.llm_name })] }, llm.llm_name));
265129
+ // `grayscale` alone is a no-op on already-black marks,
265130
+ // so fade them as well same rule as the provider grid.
265131
+ 'opacity-40 grayscale': isDisabled && !isActive,
265132
+ }), width: 32, height: 32, loading: "lazy" }) }), jsx("span", { className: "text-left text-sm font-medium text-gray-900", children: llm.llm_name })] }, llm.llm_name));
264826
265133
  }) })] }) }));
264827
265134
  }
264828
265135
 
@@ -264847,6 +265154,10 @@ function AgentLLMTab({ showConfigurationHeader = true, getLLMProviderDetails, la
264847
265154
  }, {
264848
265155
  skip: !tenantKey || !username,
264849
265156
  });
265157
+ // Two alphabetical groups: providers we have a usable LLM key for first, then
265158
+ // the ones we don't. Ordering is independent of the search filter below, so it
265159
+ // holds for whatever the filter leaves.
265160
+ const sortedLLMProviders = React__default.useMemo(() => sortLLMProvidersByCredentials(llmProviders !== null && llmProviders !== void 0 ? llmProviders : [], getLLMProviderDetails), [llmProviders, getLLMProviderDetails]);
264850
265161
  const [editMentor, { isLoading: isEditingMentor }] = useEditMentorMutation();
264851
265162
  const isDisabled = isMentorSettingsLoading || isLoadingLLMProviders || isEditingMentor;
264852
265163
  const isLoading = isMentorSettingsLoading || isLoadingLLMProviders;
@@ -264876,10 +265187,21 @@ function AgentLLMTab({ showConfigurationHeader = true, getLLMProviderDetails, la
264876
265187
  overflowX: 'hidden',
264877
265188
  }, children: jsxs("div", { className: "space-y-6", children: [jsxs("div", { className: "relative", children: [jsx(Search, { className: "absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-gray-500" }), jsx(Input, { type: "search", placeholder: labels.search.placeholder, className: "w-full py-6 pl-9 md:w-1/2", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), disabled: isDisabled })] }), isLoading ? (jsx("div", { className: "flex items-center justify-center py-10", children: jsx(Spinner, {}) })) : (jsx(WithFormPermissions, { name: "llm_provider",
264878
265189
  // @ts-ignore
264879
- permissions: (_a = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.permissions) === null || _a === void 0 ? void 0 : _a.field, enableRBAC: enableRBAC, children: ({ disabled }) => (jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4", children: llmProviders === null || llmProviders === void 0 ? void 0 : llmProviders.filter((model) => model.name.toLowerCase().includes(searchQuery.toLowerCase())).map((model) => {
265190
+ permissions: (_a = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.permissions) === null || _a === void 0 ? void 0 : _a.field, enableRBAC: enableRBAC, children: ({ disabled }) => (jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4", children: sortedLLMProviders
265191
+ .filter((model) => model.name.toLowerCase().includes(searchQuery.toLowerCase()))
265192
+ .map((model) => {
264880
265193
  const providerDetails = getLLMProviderDetails(model.name);
264881
- return (jsxs("div", { className: cn('flex cursor-pointer items-center gap-3 rounded-lg border border-gray-200 bg-white p-4 shadow-sm transition-shadow hover:shadow-md', {
264882
- 'border-blue-500': (mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.llm_provider) === model.name,
265194
+ const isActive = (mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.llm_provider) === model.name;
265195
+ // The generated LLM response type doesn't declare the
265196
+ // credential flags the backend actually sends, so read them
265197
+ // through the access-shaped view the helper expects.
265198
+ const isGrayed = !canAccessProvider(model) && !isActive;
265199
+ return (jsxs("div", { "data-testid": "llm-provider-card", "data-provider": model.name, "data-disabled": isGrayed ? 'true' : 'false', className: cn('flex cursor-pointer items-center gap-3 rounded-lg border border-gray-200 bg-white p-4 shadow-sm transition-shadow hover:shadow-md', {
265200
+ 'border-blue-500': isActive,
265201
+ // Tint the whole card too: desaturating a logo that
265202
+ // is already black changes nothing, so the card
265203
+ // itself has to carry some of the inactive signal.
265204
+ 'border-gray-100 bg-gray-50': isGrayed,
264883
265205
  }), onClick: () => {
264884
265206
  if (isDisabled || disabled)
264885
265207
  return;
@@ -264896,7 +265218,12 @@ function AgentLLMTab({ showConfigurationHeader = true, getLLMProviderDetails, la
264896
265218
  // @ts-ignore - can_use_main_keys property does not exist on LLMResponse type
264897
265219
  can_use_main_keys: model === null || model === void 0 ? void 0 : model.can_use_main_keys,
264898
265220
  });
264899
- }, children: [jsx("div", { className: "h-8 w-8 flex-shrink-0", children: jsx(Image$4, { src: providerDetails.logo, alt: t('tabsLlmTab.providerLogoAlt', { name: providerDetails.name }), className: "h-full w-full object-contain", width: 32, height: 32, loading: "lazy" }) }), jsx("span", { className: "text-sm font-medium text-gray-900", children: providerDetails.name })] }, model.id));
265221
+ }, children: [jsx("div", { className: "h-8 w-8 flex-shrink-0", children: jsx(Image$4, { src: providerDetails.logo, alt: t('tabsLlmTab.providerLogoAlt', { name: providerDetails.name }), className: cn('h-full w-full object-contain', {
265222
+ // `grayscale` only desaturates, so already-black
265223
+ // marks (OpenAI, xAI) looked untouched. Fading is
265224
+ // what actually reads as inactive at any hue.
265225
+ 'opacity-40 grayscale': isGrayed,
265226
+ }), width: 32, height: 32, loading: "lazy" }) }), jsx("span", { className: "text-sm font-medium text-gray-900", children: providerDetails.name })] }, model.id));
264900
265227
  }) })) })), selectedLLMProvider && mentorSettings && (jsx(LLMProviderModal, { isOpen: true, onClose: () => setSelectedLLMProvider(null), onSelect: updateMentorLLM, llmProvider: selectedLLMProvider, isSelecting: isEditingMentor, mentorSettings: {
264901
265228
  llm_name: mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.llm_name,
264902
265229
  llm_provider: mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.llm_provider,
@@ -265022,7 +265349,7 @@ const BulkDeleteMemoryModal$1 = dynamic(() => Promise.resolve().then(function ()
265022
265349
  const ManageCategoriesModal$1 = dynamic(() => Promise.resolve().then(function () { return manageCategoriesModal; }).then((module) => ({
265023
265350
  default: module.ManageCategoriesModal,
265024
265351
  })), { ssr: false });
265025
- const PAGE_SIZE$2 = 20;
265352
+ const PAGE_SIZE$3 = 20;
265026
265353
  const SNAPSHOT_PAGE_SIZE = 1000;
265027
265354
  function ManageMemories({ tenantKey, username, mentorId }) {
265028
265355
  var _a, _b, _c, _d, _e;
@@ -265037,7 +265364,7 @@ function ManageMemories({ tenantKey, username, mentorId }) {
265037
265364
  setPage(1);
265038
265365
  }, [selectedLearner, dateRange, selectedCategorySlug]);
265039
265366
  const listParams = useMemo(() => {
265040
- const params = { page, page_size: PAGE_SIZE$2 };
265367
+ const params = { page, page_size: PAGE_SIZE$3 };
265041
265368
  if (selectedLearner)
265042
265369
  params.email = selectedLearner;
265043
265370
  if (selectedCategorySlug !== 'all')
@@ -265056,7 +265383,7 @@ function ManageMemories({ tenantKey, username, mentorId }) {
265056
265383
  }, {
265057
265384
  skip: !tenantKey || !username || !mentorId,
265058
265385
  });
265059
- const totalPages = Math.max(1, Math.ceil(((_a = listResponse === null || listResponse === void 0 ? void 0 : listResponse.count) !== null && _a !== void 0 ? _a : 0) / PAGE_SIZE$2));
265386
+ const totalPages = Math.max(1, Math.ceil(((_a = listResponse === null || listResponse === void 0 ? void 0 : listResponse.count) !== null && _a !== void 0 ? _a : 0) / PAGE_SIZE$3));
265060
265387
  const { data: adminCategories } = useGetMemoryCategoriesAdminQuery({
265061
265388
  org: tenantKey,
265062
265389
  mentorId,
@@ -267986,7 +268313,7 @@ function toTitleCase(name) {
267986
268313
  .join(' ');
267987
268314
  }
267988
268315
 
267989
- const PAGE_SIZE$1 = 20;
268316
+ const PAGE_SIZE$2 = 20;
267990
268317
  function VoicePicker({ org, userId, provider, selectedVoiceId, onSelect, disabled, labels, }) {
267991
268318
  var _a, _b;
267992
268319
  const t = useT();
@@ -268006,13 +268333,13 @@ function VoicePicker({ org, userId, provider, selectedVoiceId, onSelect, disable
268006
268333
  userId,
268007
268334
  provider,
268008
268335
  page,
268009
- pageSize: PAGE_SIZE$1,
268336
+ pageSize: PAGE_SIZE$2,
268010
268337
  ...(debouncedSearch ? { search: debouncedSearch } : {}),
268011
268338
  }, { skip: !org || !userId });
268012
268339
  const paginated = data;
268013
268340
  const voices = (_a = paginated === null || paginated === void 0 ? void 0 : paginated.results) !== null && _a !== void 0 ? _a : [];
268014
268341
  const total = (_b = paginated === null || paginated === void 0 ? void 0 : paginated.count) !== null && _b !== void 0 ? _b : 0;
268015
- const totalPages = total > 0 ? Math.ceil(total / PAGE_SIZE$1) : 1;
268342
+ const totalPages = total > 0 ? Math.ceil(total / PAGE_SIZE$2) : 1;
268016
268343
  // Whenever a voice id is saved on the mentor settings, fetch it directly
268017
268344
  // so we can pin it at the top of the list. Otherwise the user can land
268018
268345
  // on a page that doesn't contain the selected voice and the selection
@@ -268904,11 +269231,12 @@ const AGENT_GRADER_TAB_LABELS = {
268904
269231
  offHint: 'Turn it on to write grading instructions and build your rubric. Anything you set up here is kept safe if you later turn it off.',
268905
269232
  },
268906
269233
  subTabs: {
268907
- setup: 'Grading setup',
269234
+ setup: 'Grading Setup',
268908
269235
  rubric: 'Rubric',
269236
+ results: 'Results',
268909
269237
  },
268910
269238
  denied: {
268911
- title: 'No access to grading settings',
269239
+ title: 'No Access to Grading Settings',
268912
269240
  description: "You don't have permission to view this agent's grading setup. Ask an administrator for access.",
268913
269241
  },
268914
269242
  warnings: {
@@ -268916,12 +269244,12 @@ const AGENT_GRADER_TAB_LABELS = {
268916
269244
  noCriteria: 'Grading is on but the rubric is empty — the agent will fail when asked to grade. Add at least one criterion in the Rubric tab.',
268917
269245
  },
268918
269246
  config: {
268919
- sectionTitle: 'Grading setup',
269247
+ sectionTitle: 'Grading Setup',
268920
269248
  gradingMode: {
268921
- label: 'What gets graded',
269249
+ label: 'What Gets Graded',
268922
269250
  options: {
268923
- submission: 'A submission',
268924
- conversation: 'The conversation',
269251
+ submission: 'A Submission',
269252
+ conversation: 'The Conversation',
268925
269253
  },
268926
269254
  help: {
268927
269255
  submission: 'The agent grades a piece of work the person hands in, like an essay or answer.',
@@ -268929,16 +269257,16 @@ const AGENT_GRADER_TAB_LABELS = {
268929
269257
  },
268930
269258
  },
268931
269259
  feedbackMode: {
268932
- label: 'Feedback shared with the person',
269260
+ label: 'Feedback Shared with the Person',
268933
269261
  options: {
268934
- overall: 'Overall feedback only',
268935
- perCriteria: 'Feedback per criterion',
268936
- both: 'Overall + per criterion',
269262
+ overall: 'Overall Feedback Only',
269263
+ perCriteria: 'Feedback per Criterion',
269264
+ both: 'Overall + per Criterion',
268937
269265
  },
268938
269266
  help: 'The overall score is always calculated — this only controls how much detail is shared back.',
268939
269267
  },
268940
269268
  instructions: {
268941
- label: 'Grading instructions',
269269
+ label: 'Grading Instructions',
268942
269270
  placeholder: "Describe what's being graded and anything the grader should know beyond the rubric. E.g. 'You are grading a 500-word persuasive essay on climate policy written by a high-school student. Be encouraging but honest.'",
268943
269271
  help: 'Required. This is the context the agent uses every time it grades.',
268944
269272
  },
@@ -268950,7 +269278,7 @@ const AGENT_GRADER_TAB_LABELS = {
268950
269278
  description: 'Each row is one thing the agent looks for and how many points it is worth. The overall score is points earned out of the total.',
268951
269279
  needsConfigHint: 'Save your grading setup first, then add rubric criteria here.',
268952
269280
  emptyState: 'No criteria yet. Add your first one — for example "Clarity", 10 points.',
268953
- addButton: 'Add criterion',
269281
+ addButton: 'Add Criterion',
268954
269282
  columns: {
268955
269283
  name: 'Name',
268956
269284
  criteria: 'Criteria',
@@ -268959,12 +269287,12 @@ const AGENT_GRADER_TAB_LABELS = {
268959
269287
  actionsAria: (name) => `Actions for ${name}`,
268960
269288
  edit: 'Edit',
268961
269289
  delete: 'Delete',
268962
- totalPoints: 'Total possible points: {total}',
269290
+ totalPoints: 'Total Possible Points: {total}',
268963
269291
  scoreHint: 'Overall score = points earned ÷ {total}.',
268964
269292
  lastCriterionHint: 'A rubric needs at least one criterion — add another before removing this one.',
268965
269293
  modal: {
268966
- addTitle: 'Add criterion',
268967
- editTitle: 'Edit criterion',
269294
+ addTitle: 'Add Criterion',
269295
+ editTitle: 'Edit Criterion',
268968
269296
  name: {
268969
269297
  label: 'Name',
268970
269298
  placeholder: 'e.g. Clarity',
@@ -268986,7 +269314,7 @@ const AGENT_GRADER_TAB_LABELS = {
268986
269314
  cancel: 'Cancel',
268987
269315
  },
268988
269316
  deleteModal: {
268989
- title: 'Delete criterion',
269317
+ title: 'Delete Criterion',
268990
269318
  confirmationPrefix: 'Are you sure you want to remove',
268991
269319
  confirmationSuffix: ' from the rubric?',
268992
269320
  cancel: 'Cancel',
@@ -268994,6 +269322,59 @@ const AGENT_GRADER_TAB_LABELS = {
268994
269322
  deleting: 'Deleting…',
268995
269323
  },
268996
269324
  },
269325
+ results: {
269326
+ sectionTitle: 'Grade Results',
269327
+ description: 'Every grade this agent has issued. Override a score to correct it — the change is pushed back to the LMS the grade came from.',
269328
+ filters: {
269329
+ searchUser: 'Search for User',
269330
+ searchUsersPlaceholder: 'Search users...',
269331
+ noUsersFound: 'No users found.',
269332
+ allUsers: 'All Users',
269333
+ statusLabel: 'Score Status',
269334
+ dateRangeLabel: 'Pick a Date Range',
269335
+ allStatuses: 'All Statuses',
269336
+ },
269337
+ statusValues: {
269338
+ pending: 'Pending',
269339
+ published: 'Published',
269340
+ failed: 'Failed',
269341
+ },
269342
+ columns: {
269343
+ learner: 'Learner',
269344
+ score: 'Score',
269345
+ status: 'Status',
269346
+ override: 'Override',
269347
+ gradedAt: 'Graded',
269348
+ },
269349
+ emptyState: 'No grades yet. They will appear here once the agent starts grading.',
269350
+ emptyFiltered: 'No grades match the current filters.',
269351
+ overriddenBadge: 'Overridden',
269352
+ overrideButton: 'Override',
269353
+ overrideButtonAria: (email) => `Override grade for ${email}`,
269354
+ overrideModal: {
269355
+ title: 'Override Grade',
269356
+ learnerLabel: 'Learner',
269357
+ aiScoreLabel: 'AI Score',
269358
+ currentOverrideLabel: 'Current Override',
269359
+ noOverride: 'None',
269360
+ pointsLabel: 'Override Points',
269361
+ pointsHelp: 'Between 0 and {total}. The score pushed to the LMS becomes points ÷ {total}.',
269362
+ pointsRange: 'Points must be between 0 and {total}',
269363
+ feedbackLabel: 'Override Feedback',
269364
+ feedbackPlaceholder: 'Explain the change for the learner (optional).',
269365
+ clearHelp: 'Clearing the override restores the AI score and pushes it back to the LMS.',
269366
+ save: 'Save',
269367
+ saving: 'Saving…',
269368
+ clear: 'Clear',
269369
+ clearing: 'Clearing…',
269370
+ cancel: 'Cancel',
269371
+ },
269372
+ toasts: {
269373
+ overrideSaved: 'Override saved and pushed to the LMS',
269374
+ overrideCleared: 'Override cleared — the AI score was restored',
269375
+ overrideError: "Couldn't save the override",
269376
+ },
269377
+ },
268997
269378
  toasts: {
268998
269379
  toggleOn: 'Grading turned on',
268999
269380
  toggleOff: 'Grading turned off — your rubric is kept for next time',
@@ -269020,6 +269401,7 @@ function buildGraderTabLabels(t) {
269020
269401
  subTabs: {
269021
269402
  setup: t('graderTabLabels.subTabs.setup'),
269022
269403
  rubric: t('graderTabLabels.subTabs.rubric'),
269404
+ results: t('graderTabLabels.subTabs.results'),
269023
269405
  },
269024
269406
  denied: {
269025
269407
  title: t('graderTabLabels.denied.title'),
@@ -269107,6 +269489,59 @@ function buildGraderTabLabels(t) {
269107
269489
  deleting: t('graderTabLabels.criteria.deleteModal.deleting'),
269108
269490
  },
269109
269491
  },
269492
+ results: {
269493
+ sectionTitle: t('graderTabLabels.results.sectionTitle'),
269494
+ description: t('graderTabLabels.results.description'),
269495
+ filters: {
269496
+ searchUser: t('graderTabLabels.results.filters.searchUser'),
269497
+ searchUsersPlaceholder: t('graderTabLabels.results.filters.searchUsersPlaceholder'),
269498
+ noUsersFound: t('graderTabLabels.results.filters.noUsersFound'),
269499
+ allUsers: t('graderTabLabels.results.filters.allUsers'),
269500
+ statusLabel: t('graderTabLabels.results.filters.statusLabel'),
269501
+ dateRangeLabel: t('graderTabLabels.results.filters.dateRangeLabel'),
269502
+ allStatuses: t('graderTabLabels.results.filters.allStatuses'),
269503
+ },
269504
+ statusValues: {
269505
+ pending: t('graderTabLabels.results.statusValues.pending'),
269506
+ published: t('graderTabLabels.results.statusValues.published'),
269507
+ failed: t('graderTabLabels.results.statusValues.failed'),
269508
+ },
269509
+ columns: {
269510
+ learner: t('graderTabLabels.results.columns.learner'),
269511
+ score: t('graderTabLabels.results.columns.score'),
269512
+ status: t('graderTabLabels.results.columns.status'),
269513
+ override: t('graderTabLabels.results.columns.override'),
269514
+ gradedAt: t('graderTabLabels.results.columns.gradedAt'),
269515
+ },
269516
+ emptyState: t('graderTabLabels.results.emptyState'),
269517
+ emptyFiltered: t('graderTabLabels.results.emptyFiltered'),
269518
+ overriddenBadge: t('graderTabLabels.results.overriddenBadge'),
269519
+ overrideButton: t('graderTabLabels.results.overrideButton'),
269520
+ overrideButtonAria: (email) => t('graderTabLabels.results.overrideButtonAria', { email }),
269521
+ overrideModal: {
269522
+ title: t('graderTabLabels.results.overrideModal.title'),
269523
+ learnerLabel: t('graderTabLabels.results.overrideModal.learnerLabel'),
269524
+ aiScoreLabel: t('graderTabLabels.results.overrideModal.aiScoreLabel'),
269525
+ currentOverrideLabel: t('graderTabLabels.results.overrideModal.currentOverrideLabel'),
269526
+ noOverride: t('graderTabLabels.results.overrideModal.noOverride'),
269527
+ pointsLabel: t('graderTabLabels.results.overrideModal.pointsLabel'),
269528
+ pointsHelp: t('graderTabLabels.results.overrideModal.pointsHelp'),
269529
+ pointsRange: t('graderTabLabels.results.overrideModal.pointsRange'),
269530
+ feedbackLabel: t('graderTabLabels.results.overrideModal.feedbackLabel'),
269531
+ feedbackPlaceholder: t('graderTabLabels.results.overrideModal.feedbackPlaceholder'),
269532
+ clearHelp: t('graderTabLabels.results.overrideModal.clearHelp'),
269533
+ save: t('graderTabLabels.results.overrideModal.save'),
269534
+ saving: t('graderTabLabels.results.overrideModal.saving'),
269535
+ clear: t('graderTabLabels.results.overrideModal.clear'),
269536
+ clearing: t('graderTabLabels.results.overrideModal.clearing'),
269537
+ cancel: t('graderTabLabels.results.overrideModal.cancel'),
269538
+ },
269539
+ toasts: {
269540
+ overrideSaved: t('graderTabLabels.results.toasts.overrideSaved'),
269541
+ overrideCleared: t('graderTabLabels.results.toasts.overrideCleared'),
269542
+ overrideError: t('graderTabLabels.results.toasts.overrideError'),
269543
+ },
269544
+ },
269110
269545
  toasts: {
269111
269546
  toggleOn: t('graderTabLabels.toasts.toggleOn'),
269112
269547
  toggleOff: t('graderTabLabels.toasts.toggleOff'),
@@ -269127,6 +269562,141 @@ function resolveGraderTabLabels(override, t) {
269127
269562
  return deepMerge(base, override);
269128
269563
  }
269129
269564
 
269565
+ function formatPercent$1(score) {
269566
+ return `${Math.round(score * 100)}%`;
269567
+ }
269568
+ function errorDetail$1(error) {
269569
+ var _a;
269570
+ const detail = (_a = error === null || error === void 0 ? void 0 : error.data) === null || _a === void 0 ? void 0 : _a.detail;
269571
+ return typeof detail === 'string' ? detail : '';
269572
+ }
269573
+ /**
269574
+ * Popup that records a human override for one grade result and pushes it to
269575
+ * the LMS the grade came from. Points are in rubric points (0 to the
269576
+ * rubric's total); clearing restores the AI score.
269577
+ */
269578
+ function GradeResultOverrideModal({ isOpen, onClose, result, tenantKey, mentorId, labels, }) {
269579
+ var _a, _b;
269580
+ const m = labels.overrideModal;
269581
+ // The list row doesn't carry the rubric total or existing override text —
269582
+ // fetch the full record while the modal is open.
269583
+ const { data: detail, isLoading } = useGetGradeResultQuery({ org: tenantKey, mentorId, resultId: (_a = result === null || result === void 0 ? void 0 : result.id) !== null && _a !== void 0 ? _a : '' }, { skip: !isOpen || !result });
269584
+ const [overrideGradeResult, { isLoading: isSaving }] = useOverrideGradeResultMutation();
269585
+ const [points, setPoints] = React__default.useState('');
269586
+ const [feedback, setFeedback] = React__default.useState('');
269587
+ const [showErrors, setShowErrors] = React__default.useState(false);
269588
+ const [isClearing, setIsClearing] = React__default.useState(false);
269589
+ // Prefill from the fetched record each time the modal opens.
269590
+ React__default.useEffect(() => {
269591
+ var _a;
269592
+ if (!isOpen)
269593
+ return;
269594
+ setShowErrors(false);
269595
+ setPoints((detail === null || detail === void 0 ? void 0 : detail.override_points) != null ? String(detail.override_points) : '');
269596
+ setFeedback((_a = detail === null || detail === void 0 ? void 0 : detail.override_feedback) !== null && _a !== void 0 ? _a : '');
269597
+ }, [isOpen, detail === null || detail === void 0 ? void 0 : detail.id, detail === null || detail === void 0 ? void 0 : detail.override_points, detail === null || detail === void 0 ? void 0 : detail.override_feedback]);
269598
+ const totalPoints = (_b = detail === null || detail === void 0 ? void 0 : detail.total_points) !== null && _b !== void 0 ? _b : 0;
269599
+ // Hard UI cap: overrides are entered as 0–100, additionally bounded by the
269600
+ // rubric's own total when it is smaller.
269601
+ const maxPoints = totalPoints > 0 ? Math.min(totalPoints, 100) : 100;
269602
+ const parsedPoints = Number.parseFloat(points);
269603
+ const pointsValid = Number.isFinite(parsedPoints) && parsedPoints >= 0 && parsedPoints <= maxPoints;
269604
+ const hasExistingOverride = (detail === null || detail === void 0 ? void 0 : detail.override_points) != null;
269605
+ const submit = async (formData) => {
269606
+ if (!result)
269607
+ return false;
269608
+ try {
269609
+ await overrideGradeResult({
269610
+ org: tenantKey,
269611
+ mentorId,
269612
+ resultId: result.id,
269613
+ formData,
269614
+ }).unwrap();
269615
+ return true;
269616
+ }
269617
+ catch (error) {
269618
+ console.error('[GradeResultOverrideModal] override error', error);
269619
+ toast.error(errorDetail$1(error) || labels.toasts.overrideError);
269620
+ return false;
269621
+ }
269622
+ };
269623
+ const handleSave = async () => {
269624
+ if (!pointsValid) {
269625
+ setShowErrors(true);
269626
+ return;
269627
+ }
269628
+ const saved = await submit({ override_points: parsedPoints, override_feedback: feedback });
269629
+ if (saved) {
269630
+ toast.success(labels.toasts.overrideSaved);
269631
+ onClose();
269632
+ }
269633
+ };
269634
+ const handleClear = async () => {
269635
+ setIsClearing(true);
269636
+ const cleared = await submit({ override_points: null });
269637
+ setIsClearing(false);
269638
+ if (cleared) {
269639
+ toast.success(labels.toasts.overrideCleared);
269640
+ onClose();
269641
+ }
269642
+ };
269643
+ return (jsx(Dialog, { open: isOpen, onOpenChange: onClose, children: jsxs(DialogContent, { "aria-describedby": "grader-override-modal-description", "data-testid": "grader-override-modal", children: [jsx(DialogHeader, { children: jsx(DialogTitle, { className: "ibl-dialog-title", children: m.title }) }), isLoading || !detail ? (jsx("div", { className: "flex items-center justify-center py-8", "data-testid": "grader-override-loading", children: jsx(Spinner, {}) })) : (jsxs("div", { className: "space-y-4", id: "grader-override-modal-description", children: [jsxs("div", { className: "grid grid-cols-2 gap-2 rounded-lg border border-gray-200 bg-gray-50/60 p-3 text-sm", children: [jsx("span", { className: "text-gray-500", children: m.learnerLabel }), jsx("span", { className: "truncate text-gray-900", title: detail.student.email, children: detail.student.email }), jsx("span", { className: "text-gray-500", children: m.aiScoreLabel }), jsx("span", { className: "text-gray-900", children: formatPercent$1(detail.score) }), jsx("span", { className: "text-gray-500", children: m.currentOverrideLabel }), jsx("span", { className: "text-gray-900", "data-testid": "grader-override-current", children: hasExistingOverride ? `${detail.override_points} / ${totalPoints}` : m.noOverride })] }), jsxs("div", { className: "space-y-1.5", children: [jsx(Label$1, { htmlFor: "grader-override-points", children: m.pointsLabel }), jsx(Input, { id: "grader-override-points", type: "number", min: 0, max: maxPoints, step: "any", value: points, className: "w-28", onChange: (e) => setPoints(e.target.value) }), jsx("p", { className: "text-xs text-gray-500", children: m.pointsHelp.replace('{total}', String(maxPoints)) }), showErrors && !pointsValid && (jsx("p", { className: "text-xs text-red-500", children: m.pointsRange.replace('{total}', String(maxPoints)) }))] }), jsxs("div", { className: "space-y-1.5", children: [jsx(Label$1, { htmlFor: "grader-override-feedback", children: m.feedbackLabel }), jsx(Textarea, { id: "grader-override-feedback", value: feedback, placeholder: m.feedbackPlaceholder, rows: 3, onChange: (e) => setFeedback(e.target.value) })] }), hasExistingOverride && jsx("p", { className: "text-xs text-gray-500", children: m.clearHelp })] })), jsxs(DialogFooter, { className: "gap-3", children: [hasExistingOverride && (jsx(Button$1, { variant: "outline", className: "mr-auto text-red-600 hover:text-red-700", onClick: handleClear, disabled: isSaving || isLoading, "data-testid": "grader-override-clear", children: isClearing ? m.clearing : m.clear })), jsx(Button$1, { variant: "outline", onClick: onClose, children: m.cancel }), jsx(Button$1, { className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", onClick: handleSave, disabled: isSaving || isLoading, "data-testid": "grader-override-save", children: isSaving && !isClearing ? m.saving : m.save })] })] }) }));
269644
+ }
269645
+
269646
+ const PAGE_SIZE$1 = 10;
269647
+ const STATUS_ALL = 'all';
269648
+ function formatPercent(score) {
269649
+ return `${Math.round(score * 100)}%`;
269650
+ }
269651
+ function ResultsSection({ labels, tenantKey, mentorId, username, canOverride, }) {
269652
+ var _a, _b, _c;
269653
+ const [selectedEmail, setSelectedEmail] = React__default.useState('');
269654
+ const [status, setStatus] = React__default.useState(STATUS_ALL);
269655
+ const [dateRange, setDateRange] = React__default.useState(undefined);
269656
+ const [page, setPage] = React__default.useState(1);
269657
+ const [resultToOverride, setResultToOverride] = React__default.useState(null);
269658
+ const gradedAtAfter = (dateRange === null || dateRange === void 0 ? void 0 : dateRange.from)
269659
+ ? `${format$1(dateRange.from, 'yyyy-MM-dd')}T00:00:00Z`
269660
+ : undefined;
269661
+ const gradedAtBefore = (dateRange === null || dateRange === void 0 ? void 0 : dateRange.to)
269662
+ ? `${format$1(dateRange.to, 'yyyy-MM-dd')}T23:59:59Z`
269663
+ : undefined;
269664
+ const hasFilters = Boolean(selectedEmail) ||
269665
+ status !== STATUS_ALL ||
269666
+ Boolean(gradedAtAfter) ||
269667
+ Boolean(gradedAtBefore);
269668
+ // Any filter change restarts from the first page.
269669
+ React__default.useEffect(() => {
269670
+ setPage(1);
269671
+ }, [selectedEmail, status, gradedAtAfter, gradedAtBefore]);
269672
+ // Same learner list the History tab's "Search for User" control uses.
269673
+ const { data: chatHistoryFilter } = useGetChatHistoryFilterQuery({
269674
+ org: tenantKey,
269675
+ // @ts-expect-error userId is accepted by the API but not typed
269676
+ userId: username || '',
269677
+ mentorId,
269678
+ });
269679
+ const learners = (_a = chatHistoryFilter === null || chatHistoryFilter === void 0 ? void 0 : chatHistoryFilter.users) !== null && _a !== void 0 ? _a : [];
269680
+ const { data, isLoading, isFetching } = useListGradeResultsQuery({
269681
+ org: tenantKey,
269682
+ mentorId,
269683
+ email: selectedEmail || undefined,
269684
+ status: status === STATUS_ALL ? undefined : status,
269685
+ graded_at_after: gradedAtAfter,
269686
+ graded_at_before: gradedAtBefore,
269687
+ page,
269688
+ page_size: PAGE_SIZE$1,
269689
+ }, { skip: !tenantKey || !mentorId });
269690
+ const results = (_b = data === null || data === void 0 ? void 0 : data.results) !== null && _b !== void 0 ? _b : [];
269691
+ const totalPages = Math.max(1, Math.ceil(((_c = data === null || data === void 0 ? void 0 : data.count) !== null && _c !== void 0 ? _c : 0) / PAGE_SIZE$1));
269692
+ const statusText = (value) => value ? labels.statusValues[value] : '—';
269693
+ return (jsxs("div", { className: "space-y-3", "data-testid": "grader-results-section", children: [jsxs("div", { children: [jsx("h4", { className: "text-sm font-medium text-gray-900", children: labels.sectionTitle }), jsx("p", { className: "text-xs text-gray-600", children: labels.description })] }), jsx("div", { className: "rounded-lg border p-4", children: jsxs("div", { className: "flex flex-col gap-3 lg:flex-row", children: [jsx("div", { className: "relative min-w-[200px] flex-1", children: jsxs(Popover, { children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button$1, { variant: "outline", role: "combobox", "aria-label": labels.filters.searchUser, className: "w-full justify-between bg-transparent font-normal", "data-testid": "grader-results-user-filter", children: [selectedEmail || labels.filters.searchUser, jsx(ChevronsUpDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })] }) }), jsx(PopoverContent, { className: "w-full p-0", align: "start", portalled: false, children: jsxs(Command, { children: [jsx(CommandInput, { placeholder: labels.filters.searchUsersPlaceholder }), jsxs(CommandList, { children: [jsx(CommandEmpty, { children: labels.filters.noUsersFound }), jsxs(CommandGroup, { children: [jsxs(CommandItem, { value: "", onSelect: () => setSelectedEmail(''), children: [jsx(Check, { className: cn('mr-2 h-4 w-4', !selectedEmail ? 'opacity-100' : 'opacity-0') }), labels.filters.allUsers] }), learners.map((learner) => (jsxs(CommandItem, { value: learner.email, onSelect: () => setSelectedEmail(learner.email), children: [jsx(Check, { className: cn('mr-2 h-4 w-4', selectedEmail === learner.email ? 'opacity-100' : 'opacity-0') }), jsx("div", { className: "flex flex-col", children: jsx("span", { className: "font-medium text-gray-700", children: learner.email }) })] }, learner.email)))] })] })] }) })] }) }), jsxs(Select$1, { value: status, onValueChange: setStatus, children: [jsx(SelectTrigger, { className: "w-full lg:w-[160px]", "aria-label": labels.filters.statusLabel, "data-testid": "grader-results-status-filter", children: jsx(SelectValue, { placeholder: labels.filters.statusLabel }) }), jsxs(SelectContent, { children: [jsx(SelectItem, { value: STATUS_ALL, children: labels.filters.allStatuses }), jsx(SelectItem, { value: "pending", children: labels.statusValues.pending }), jsx(SelectItem, { value: "published", children: labels.statusValues.published }), jsx(SelectItem, { value: "failed", children: labels.statusValues.failed })] })] }), jsxs(Popover, { children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button$1, { variant: "outline", className: "flex w-full items-center gap-2 bg-transparent font-normal whitespace-nowrap lg:w-auto", "data-testid": "grader-results-date-filter", children: [jsx(Calendar$1, { className: "h-4 w-4" }), (dateRange === null || dateRange === void 0 ? void 0 : dateRange.from) && (dateRange === null || dateRange === void 0 ? void 0 : dateRange.to)
269694
+ ? `${format$1(dateRange.from, 'MMM dd')} - ${format$1(dateRange.to, 'MMM dd')}`
269695
+ : labels.filters.dateRangeLabel] }) }), jsx(PopoverContent, { className: "w-auto p-0", align: "start", children: jsx(Calendar, { mode: "range", selected: dateRange, onSelect: setDateRange, numberOfMonths: 2, initialFocus: true }) })] })] }) }), jsx("div", { className: "overflow-hidden rounded-md border", children: jsx("div", { className: "overflow-x-auto sm:mx-0", children: jsx("div", { className: "inline-block min-w-full align-middle", children: isLoading ? (jsx("div", { className: "flex w-full items-center justify-center py-10", children: jsx(Spinner, {}) })) : (jsxs(Table$1, { className: "min-w-full", children: [jsx(TableHeader$1, { children: jsxs(TableRow$1, { className: "bg-muted/50 border-b", children: [jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.columns.learner }), jsx(TableHead, { className: "p-3 text-right text-sm whitespace-nowrap text-[#646464]", children: labels.columns.score }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.columns.status }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.columns.override }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.columns.gradedAt }), jsx(TableHead, { className: "w-10 p-3" })] }) }), jsx(TableBody, { children: results.length === 0 ? (jsx(TableRow$1, { children: jsx(TableCell$1, { colSpan: 6, className: "p-4 text-center text-[#646464]", children: hasFilters ? labels.emptyFiltered : labels.emptyState }) })) : (results.map((result) => (jsxs(TableRow$1, { className: "border-b last:border-0", "data-testid": `grader-result-row-${result.id}`, children: [jsx(TableCell$1, { className: "max-w-[220px] truncate p-3 font-medium whitespace-nowrap text-[#646464]", title: result.student.email, children: result.student.email }), jsx(TableCell$1, { className: "p-3 text-right whitespace-nowrap text-[#646464]", children: formatPercent(result.effective_score) }), jsx(TableCell$1, { className: "p-3 whitespace-nowrap text-[#646464]", children: statusText(result.status) }), jsx(TableCell$1, { className: "min-w-[200px] max-w-[320px] p-3 text-[#646464]", children: result.override_score != null
269696
+ ? `${labels.overriddenBadge} · ${formatPercent(result.override_score)} · ${statusText(result.override_status)}`
269697
+ : '—' }), jsx(TableCell$1, { className: "p-3 whitespace-nowrap text-[#646464]", children: formatDistanceToNow(new Date(result.graded_at), { addSuffix: true }) }), jsx(TableCell$1, { className: "p-3 text-right", children: canOverride && (jsx(Button$1, { type: "button", variant: "outline", size: "sm", onClick: () => setResultToOverride(result), "aria-label": labels.overrideButtonAria(result.student.email), "data-testid": `grader-result-override-${result.id}`, children: labels.overrideButton })) })] }, result.id)))) })] })) }) }) }), totalPages > 1 && (jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: isLoading || isFetching })), jsx(GradeResultOverrideModal, { isOpen: resultToOverride !== null, onClose: () => setResultToOverride(null), result: resultToOverride, tenantKey: tenantKey, mentorId: mentorId, labels: labels })] }));
269698
+ }
269699
+
269130
269700
  function CriterionDeleteModal({ isOpen, onClose, criterion, labels, isDeleting, onConfirm, }) {
269131
269701
  const handleDelete = async () => {
269132
269702
  if (!criterion)
@@ -269178,25 +269748,25 @@ function CriterionModal({ isOpen, onClose, criterion, labels, isSaving, onSave }
269178
269748
  return (jsx(Dialog, { open: isOpen, onOpenChange: onClose, children: jsxs(DialogContent, { "aria-describedby": "grader-criterion-modal-description", "data-testid": "grader-criterion-modal", children: [jsx(DialogHeader, { children: jsx(DialogTitle, { className: "ibl-dialog-title", children: isEditing ? labels.editTitle : labels.addTitle }) }), jsxs("div", { className: "space-y-4", id: "grader-criterion-modal-description", children: [jsxs("div", { className: "space-y-1.5", children: [jsx(Label$1, { htmlFor: "grader-criterion-name", children: labels.name.label }), jsx(Input, { id: "grader-criterion-name", value: draft.name, placeholder: labels.name.placeholder, onChange: (e) => setDraft((prev) => ({ ...prev, name: e.target.value })) }), showErrors && errors.name && jsx("p", { className: "text-xs text-red-500", children: errors.name })] }), jsxs("div", { className: "space-y-1.5", children: [jsx(Label$1, { htmlFor: "grader-criterion-criteria", children: labels.criteria.label }), jsx(Textarea, { id: "grader-criterion-criteria", value: draft.criteria, placeholder: labels.criteria.placeholder, rows: 3, onChange: (e) => setDraft((prev) => ({ ...prev, criteria: e.target.value })) }), showErrors && errors.criteria && (jsx("p", { className: "text-xs text-red-500", children: errors.criteria }))] }), jsxs("div", { className: "space-y-1.5", children: [jsx(Label$1, { htmlFor: "grader-criterion-points", children: labels.points.label }), jsx(Input, { id: "grader-criterion-points", type: "number", min: 0, step: "any", value: draft.points, placeholder: labels.points.placeholder, className: "w-28", onChange: (e) => setDraft((prev) => ({ ...prev, points: e.target.value })) }), showErrors && errors.points && jsx("p", { className: "text-xs text-red-500", children: errors.points })] })] }), jsxs(DialogFooter, { className: "gap-3", children: [jsx(Button$1, { variant: "outline", onClick: onClose, children: labels.cancel }), jsx(Button$1, { className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", onClick: handleSubmit, disabled: isSaving, "data-testid": "grader-criterion-modal-save", children: isSaving ? labels.saving : labels.save })] })] }) }));
269179
269749
  }
269180
269750
 
269181
- function RubricSection({ labels, criteria, hasConfig, isLoading, isMutating, totalPoints, onAdd, onEdit, onDelete, }) {
269751
+ function RubricSection({ labels, criteria, hasConfig, isLoading, isMutating, totalPoints, canAdd, canEdit, canDelete, onAdd, onEdit, onDelete, }) {
269182
269752
  const [showCreate, setShowCreate] = React__default.useState(false);
269183
269753
  const [criterionToEdit, setCriterionToEdit] = React__default.useState(null);
269184
269754
  const [criterionToDelete, setCriterionToDelete] = React__default.useState(null);
269185
269755
  const isLastCriterion = criteria.length === 1;
269186
- return (jsxs("div", { className: "space-y-3", "data-testid": "grader-criteria-section", children: [jsxs("div", { className: "flex items-start justify-between gap-4", children: [jsxs("div", { children: [jsx("h4", { className: "text-sm font-medium text-gray-900", children: labels.sectionTitle }), jsx("p", { className: "text-xs text-gray-600", children: labels.description })] }), jsxs(Button$1, { className: "ibl-button-primary flex-shrink-0", onClick: () => setShowCreate(true), disabled: !hasConfig || isMutating, "data-testid": "grader-add-criterion-button", children: [jsx(Plus, { className: "mr-1 h-4 w-4" }), labels.addButton] })] }), jsx("div", { className: "overflow-hidden rounded-md border", children: jsx("div", { className: "overflow-x-auto sm:mx-0", children: jsx("div", { className: "inline-block min-w-full align-middle", children: isLoading ? (jsx("div", { className: "flex w-full items-center justify-center py-10", children: jsx(Spinner, {}) })) : (jsxs(Table$1, { className: "min-w-full", children: [jsx(TableHeader$1, { children: jsxs(TableRow$1, { className: "bg-muted/50 border-b", children: [jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.columns.name }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.columns.criteria }), jsx(TableHead, { className: "p-3 text-right text-sm whitespace-nowrap text-[#646464]", children: labels.columns.points }), jsx(TableHead, { className: "w-10 p-3" })] }) }), jsx(TableBody, { children: criteria.length === 0 ? (jsx(TableRow$1, { children: jsx(TableCell$1, { colSpan: 4, className: "p-4 text-center text-[#646464]", children: hasConfig ? labels.emptyState : labels.needsConfigHint }) })) : (criteria.map((criterion) => (jsxs(TableRow$1, { className: "border-b last:border-0", "data-testid": `grader-criterion-row-${criterion.id}`, children: [jsx(TableCell$1, { className: "max-w-[160px] truncate p-3 font-medium whitespace-nowrap text-[#646464]", children: criterion.name }), jsx(TableCell$1, { className: "max-w-[280px] truncate p-3 text-[#646464]", title: criterion.criteria, children: criterion.criteria }), jsx(TableCell$1, { className: "p-3 text-right whitespace-nowrap text-[#646464]", children: criterion.points }), jsx(TableCell$1, { className: "p-3 text-right", children: jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsx(Button$1, { type: "button", variant: "ghost", size: "icon", "aria-label": labels.actionsAria(criterion.name), children: jsx(Ellipsis, { className: "h-4 w-4" }) }) }), jsxs(DropdownMenuContent, { align: "end", children: [jsxs(DropdownMenuItem, { onClick: () => setCriterionToEdit(criterion), children: [jsx(Pencil, { className: "mr-2 h-4 w-4" }), labels.edit] }), jsxs(DropdownMenuItem, { className: "text-red-600 focus:text-red-700", disabled: isLastCriterion, onClick: () => {
269756
+ return (jsxs("div", { className: "space-y-3", "data-testid": "grader-criteria-section", children: [jsxs("div", { className: "flex items-start justify-between gap-4", children: [jsxs("div", { children: [jsx("h4", { className: "text-sm font-medium text-gray-900", children: labels.sectionTitle }), jsx("p", { className: "text-xs text-gray-600", children: labels.description })] }), canAdd && (jsxs(Button$1, { className: "ibl-button-primary flex-shrink-0", onClick: () => setShowCreate(true), disabled: !hasConfig || isMutating, "data-testid": "grader-add-criterion-button", children: [jsx(Plus, { className: "mr-1 h-4 w-4" }), labels.addButton] }))] }), jsx("div", { className: "overflow-hidden rounded-md border", children: jsx("div", { className: "overflow-x-auto sm:mx-0", children: jsx("div", { className: "inline-block min-w-full align-middle", children: isLoading ? (jsx("div", { className: "flex w-full items-center justify-center py-10", children: jsx(Spinner, {}) })) : (jsxs(Table$1, { className: "min-w-full", children: [jsx(TableHeader$1, { children: jsxs(TableRow$1, { className: "bg-muted/50 border-b", children: [jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.columns.name }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.columns.criteria }), jsx(TableHead, { className: "p-3 text-right text-sm whitespace-nowrap text-[#646464]", children: labels.columns.points }), jsx(TableHead, { className: "w-10 p-3" })] }) }), jsx(TableBody, { children: criteria.length === 0 ? (jsx(TableRow$1, { children: jsx(TableCell$1, { colSpan: 4, className: "p-4 text-center text-[#646464]", children: hasConfig ? labels.emptyState : labels.needsConfigHint }) })) : (criteria.map((criterion) => (jsxs(TableRow$1, { className: "border-b last:border-0", "data-testid": `grader-criterion-row-${criterion.id}`, children: [jsx(TableCell$1, { className: "max-w-[160px] truncate p-3 font-medium whitespace-nowrap text-[#646464]", children: criterion.name }), jsx(TableCell$1, { className: "max-w-[280px] truncate p-3 text-[#646464]", title: criterion.criteria, children: criterion.criteria }), jsx(TableCell$1, { className: "p-3 text-right whitespace-nowrap text-[#646464]", children: criterion.points }), jsx(TableCell$1, { className: "p-3 text-right", children: (canEdit || canDelete) && (jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsx(Button$1, { type: "button", variant: "ghost", size: "icon", "aria-label": labels.actionsAria(criterion.name), children: jsx(Ellipsis, { className: "h-4 w-4" }) }) }), jsxs(DropdownMenuContent, { align: "end", children: [canEdit && (jsxs(DropdownMenuItem, { onClick: () => setCriterionToEdit(criterion), children: [jsx(Pencil, { className: "mr-2 h-4 w-4" }), labels.edit] })), canDelete && (jsxs(DropdownMenuItem, { className: "text-red-600 focus:text-red-700", disabled: isLastCriterion, onClick: () => {
269187
269757
  // Radix marks the item disabled but a raw click can
269188
269758
  // still land — the backend refuses to delete the
269189
269759
  // last criterion, so hard-guard here too.
269190
269760
  if (isLastCriterion)
269191
269761
  return;
269192
269762
  setCriterionToDelete(criterion);
269193
- }, children: [jsx(Trash2, { className: "mr-2 h-4 w-4" }), labels.delete] })] })] }) })] }, criterion.id)))) })] })) }) }) }), criteria.length > 0 && !isLoading && (jsxs(Fragment$1, { children: [jsxs("div", { className: "flex items-center justify-between pt-1 text-xs", children: [jsx("span", { className: "font-medium text-gray-900", children: labels.totalPoints.replace('{total}', String(totalPoints)) }), jsx("span", { className: "text-gray-500", children: labels.scoreHint.replace('{total}', String(totalPoints)) })] }), isLastCriterion && (
269763
+ }, children: [jsx(Trash2, { className: "mr-2 h-4 w-4" }), labels.delete] }))] })] })) })] }, criterion.id)))) })] })) }) }) }), criteria.length > 0 && !isLoading && (jsxs(Fragment$1, { children: [jsxs("div", { className: "flex items-center justify-between pt-1 text-xs", children: [jsx("span", { className: "font-medium text-gray-900", children: labels.totalPoints.replace('{total}', String(totalPoints)) }), jsx("span", { className: "text-gray-500", children: labels.scoreHint.replace('{total}', String(totalPoints)) })] }), isLastCriterion && (
269194
269764
  // The backend refuses to delete the last criterion — explain why
269195
269765
  // its Delete menu action is disabled.
269196
269766
  jsx("p", { className: "text-xs text-gray-500", "data-testid": "grader-last-criterion-hint", children: labels.lastCriterionHint }))] })), jsx(CriterionModal, { isOpen: showCreate, onClose: () => setShowCreate(false), criterion: null, labels: labels.modal, isSaving: isMutating, onSave: onAdd }), jsx(CriterionModal, { isOpen: criterionToEdit !== null, onClose: () => setCriterionToEdit(null), criterion: criterionToEdit, labels: labels.modal, isSaving: isMutating, onSave: (values) => onEdit(criterionToEdit.id, values) }), jsx(CriterionDeleteModal, { isOpen: criterionToDelete !== null, onClose: () => setCriterionToDelete(null), criterion: criterionToDelete, labels: labels.deleteModal, isDeleting: isMutating, onConfirm: onDelete })] }));
269197
269767
  }
269198
269768
 
269199
- function SetupSection({ labels, config, isSaving, onSave }) {
269769
+ function SetupSection({ labels, config, isSaving, canSave: canSavePermission, onSave, }) {
269200
269770
  const [gradingMode, setGradingMode] = React__default.useState('submission');
269201
269771
  const [feedbackMode, setFeedbackMode] = React__default.useState('both');
269202
269772
  const [instructions, setInstructions] = React__default.useState('');
@@ -269215,11 +269785,11 @@ function SetupSection({ labels, config, isSaving, onSave }) {
269215
269785
  const canSave = instructions.trim().length > 0 && isDirty && !isSaving;
269216
269786
  return (jsxs("div", { className: "space-y-4", "data-testid": "grader-setup-section", children: [jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: [jsxs("div", { className: "space-y-1.5", children: [jsx(Label$1, { className: "text-xs font-medium text-gray-700", children: labels.gradingMode.label }), jsxs(Select$1, { value: gradingMode, onValueChange: (value) => setGradingMode(value), children: [jsx(SelectTrigger, { className: "h-9", "data-testid": "grader-grading-mode-select", children: jsx(SelectValue, {}) }), jsxs(SelectContent, { children: [jsx(SelectItem, { value: "submission", children: labels.gradingMode.options.submission }), jsx(SelectItem, { value: "conversation", children: labels.gradingMode.options.conversation })] })] }), jsx("p", { className: "text-xs text-gray-500", children: gradingMode === 'submission'
269217
269787
  ? labels.gradingMode.help.submission
269218
- : labels.gradingMode.help.conversation })] }), jsxs("div", { className: "space-y-1.5", children: [jsx(Label$1, { className: "text-xs font-medium text-gray-700", children: labels.feedbackMode.label }), jsxs(Select$1, { value: feedbackMode, onValueChange: (value) => setFeedbackMode(value), children: [jsx(SelectTrigger, { className: "h-9", "data-testid": "grader-feedback-mode-select", children: jsx(SelectValue, {}) }), jsxs(SelectContent, { children: [jsx(SelectItem, { value: "overall", children: labels.feedbackMode.options.overall }), jsx(SelectItem, { value: "per_criteria", children: labels.feedbackMode.options.perCriteria }), jsx(SelectItem, { value: "both", children: labels.feedbackMode.options.both })] })] }), jsx("p", { className: "text-xs text-gray-500", children: labels.feedbackMode.help })] })] }), jsxs("div", { className: "space-y-1.5", children: [jsx(Label$1, { className: "text-xs font-medium text-gray-700", children: labels.instructions.label }), jsx(Textarea, { value: instructions, onChange: (e) => setInstructions(e.target.value), placeholder: labels.instructions.placeholder, rows: 4, "data-testid": "grader-instructions-textarea" }), jsx("p", { className: "text-xs text-gray-500", children: labels.instructions.help })] }), jsx("div", { className: "flex items-center justify-end", children: jsx("button", { type: "button", onClick: () => onSave({
269788
+ : labels.gradingMode.help.conversation })] }), jsxs("div", { className: "space-y-1.5", children: [jsx(Label$1, { className: "text-xs font-medium text-gray-700", children: labels.feedbackMode.label }), jsxs(Select$1, { value: feedbackMode, onValueChange: (value) => setFeedbackMode(value), children: [jsx(SelectTrigger, { className: "h-9", "data-testid": "grader-feedback-mode-select", children: jsx(SelectValue, {}) }), jsxs(SelectContent, { children: [jsx(SelectItem, { value: "overall", children: labels.feedbackMode.options.overall }), jsx(SelectItem, { value: "per_criteria", children: labels.feedbackMode.options.perCriteria }), jsx(SelectItem, { value: "both", children: labels.feedbackMode.options.both })] })] }), jsx("p", { className: "text-xs text-gray-500", children: labels.feedbackMode.help })] })] }), jsxs("div", { className: "space-y-1.5", children: [jsx(Label$1, { className: "text-xs font-medium text-gray-700", children: labels.instructions.label }), jsx(Textarea, { value: instructions, onChange: (e) => setInstructions(e.target.value), placeholder: labels.instructions.placeholder, rows: 4, "data-testid": "grader-instructions-textarea" }), jsx("p", { className: "text-xs text-gray-500", children: labels.instructions.help })] }), canSavePermission && (jsx("div", { className: "flex items-center justify-end", children: jsx("button", { type: "button", onClick: () => onSave({
269219
269789
  grading_mode: gradingMode,
269220
269790
  feedback_mode: feedbackMode,
269221
269791
  grader_instructions: instructions,
269222
- }), disabled: !canSave, "data-testid": "grader-save-button", className: "inline-flex items-center gap-2 rounded-md bg-gradient-to-r from-[#2563EB] to-[#93C5FD] px-4 py-2 text-sm font-medium text-white hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50", children: isSaving ? labels.savingButton : labels.saveButton }) })] }));
269792
+ }), disabled: !canSave, "data-testid": "grader-save-button", className: "inline-flex items-center gap-2 rounded-md bg-gradient-to-r from-[#2563EB] to-[#93C5FD] px-4 py-2 text-sm font-medium text-white hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50", children: isSaving ? labels.savingButton : labels.saveButton }) }))] }));
269223
269793
  }
269224
269794
 
269225
269795
  /**
@@ -269236,7 +269806,7 @@ function errorDetail(error) {
269236
269806
  const detail = (_a = error === null || error === void 0 ? void 0 : error.data) === null || _a === void 0 ? void 0 : _a.detail;
269237
269807
  return typeof detail === 'string' ? detail : '';
269238
269808
  }
269239
- function useGrader({ tenantKey, mentorId, username, labels }) {
269809
+ function useGrader({ tenantKey, mentorId, username, labels, enableRBAC = false, rbacPermissions = {}, }) {
269240
269810
  var _a;
269241
269811
  const identityReady = Boolean(tenantKey && mentorId && username);
269242
269812
  const { data: mentorSettings, isLoading: isSettingsLoading } = useGetMentorSettingsQuery({
@@ -269273,6 +269843,25 @@ function useGrader({ tenantKey, mentorId, username, labels }) {
269273
269843
  const configNotFound = errorStatus(configError) === 404;
269274
269844
  const hasConfig = Boolean(config);
269275
269845
  const isForbidden = errorStatus(configError) === 403 || errorStatus(criteriaError) === 403;
269846
+ // Grader permissions are flat actions on the mentor resource
269847
+ // (`/mentors/{dbId}/#write_grader_config`, `#view_grade_results`, …) — the
269848
+ // same entry every other mentor check uses. The check endpoint may predate
269849
+ // these actions, so they are only enforced when the tree actually contains
269850
+ // the mentor entry; otherwise everything stays visible and the server's
269851
+ // 403s remain the source of truth.
269852
+ const mentorDbId = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.mentor_id;
269853
+ const mentorEntry = rbacPermissions[`/mentors/${mentorDbId}/`];
269854
+ const allow = (action) => !mentorEntry ||
269855
+ checkRbacPermission(rbacPermissions, `/mentors/${mentorDbId}/#${action}`, enableRBAC);
269856
+ const canReadConfig = allow('read_grader_config');
269857
+ // First save POSTs (create_grader_config), later saves PATCH (write_grader_config).
269858
+ const canSaveConfig = allow(hasConfig ? 'write_grader_config' : 'create_grader_config');
269859
+ const canViewCriteria = allow('view_grader_criteria');
269860
+ const canAddCriterion = allow('create_grader_criteria');
269861
+ const canEditCriterion = allow('write_grader_criteria');
269862
+ const canDeleteCriterion = allow('delete_grader_criteria');
269863
+ const canViewResults = allow('view_grade_results');
269864
+ const canOverrideResults = allow('override_grade_results');
269276
269865
  const totalPoints = criteria.reduce((sum, criterion) => sum + (Number(criterion.points) || 0), 0);
269277
269866
  const toggleGrading = async (checked) => {
269278
269867
  var _a, _b, _c;
@@ -269382,6 +269971,14 @@ function useGrader({ tenantKey, mentorId, username, labels }) {
269382
269971
  return {
269383
269972
  isLoading: isSettingsLoading || isConfigLoading,
269384
269973
  isForbidden,
269974
+ canReadConfig,
269975
+ canSaveConfig,
269976
+ canViewCriteria,
269977
+ canAddCriterion,
269978
+ canEditCriterion,
269979
+ canDeleteCriterion,
269980
+ canViewResults,
269981
+ canOverrideResults,
269385
269982
  enabled,
269386
269983
  isToggling,
269387
269984
  toggleGrading,
@@ -269403,6 +270000,7 @@ function useGrader({ tenantKey, mentorId, username, labels }) {
269403
270000
  const GRADER_SUB_TABS = {
269404
270001
  setup: 'setup',
269405
270002
  rubric: 'rubric',
270003
+ results: 'results',
269406
270004
  };
269407
270005
  /**
269408
270006
  * Standalone top-level tab for the agent's grading setup: the in-tab toggle
@@ -269415,15 +270013,26 @@ const GRADER_SUB_TABS = {
269415
270013
  * rubric has at least one criterion — the tab surfaces a warning whenever
269416
270014
  * the tool is on but either of the other two is missing.
269417
270015
  */
269418
- function AgentGraderTab({ labels: labelsOverride, tenantKey: tenantKeyProp, mentorId: mentorIdProp, username: usernameProp, }) {
269419
- var _a, _b, _c;
270016
+ function AgentGraderTab({ labels: labelsOverride, tenantKey: tenantKeyProp, mentorId: mentorIdProp, username: usernameProp, enableRBAC: enableRBACProp, rbacPermissions: rbacPermissionsProp, }) {
270017
+ var _a, _b, _c, _d, _e;
269420
270018
  const ctx = useAgentSettingsOptional();
269421
270019
  const tenantKey = (_a = tenantKeyProp !== null && tenantKeyProp !== void 0 ? tenantKeyProp : ctx === null || ctx === void 0 ? void 0 : ctx.tenantKey) !== null && _a !== void 0 ? _a : '';
269422
270020
  const mentorId = (_b = mentorIdProp !== null && mentorIdProp !== void 0 ? mentorIdProp : ctx === null || ctx === void 0 ? void 0 : ctx.mentorId) !== null && _b !== void 0 ? _b : '';
269423
270021
  const username = (_c = usernameProp !== null && usernameProp !== void 0 ? usernameProp : ctx === null || ctx === void 0 ? void 0 : ctx.username) !== null && _c !== void 0 ? _c : '';
270022
+ const enableRBAC = (_d = enableRBACProp !== null && enableRBACProp !== void 0 ? enableRBACProp : ctx === null || ctx === void 0 ? void 0 : ctx.enableRBAC) !== null && _d !== void 0 ? _d : false;
270023
+ const rbacPermissions = (_e = rbacPermissionsProp !== null && rbacPermissionsProp !== void 0 ? rbacPermissionsProp : ctx === null || ctx === void 0 ? void 0 : ctx.rbacPermissions) !== null && _e !== void 0 ? _e : {};
269424
270024
  const t = useT();
269425
270025
  const labels = React__default.useMemo(() => resolveGraderTabLabels(labelsOverride, t), [labelsOverride, t]);
269426
- const { isLoading, isForbidden, enabled, isToggling, toggleGrading, config, hasConfig, isSavingConfig, saveConfig, criteria, isCriteriaLoading, totalPoints, addCriterion, editCriterion, removeCriterion, isMutatingCriteria, } = useGrader({ tenantKey, mentorId, username, labels });
270026
+ const { isLoading, isForbidden, enabled, isToggling, toggleGrading, config, hasConfig, isSavingConfig, saveConfig, criteria, isCriteriaLoading, totalPoints, addCriterion, editCriterion, removeCriterion, isMutatingCriteria, canReadConfig, canSaveConfig, canViewCriteria, canAddCriterion, canEditCriterion, canDeleteCriterion, canViewResults, canOverrideResults, } = useGrader({ tenantKey, mentorId, username, labels, enableRBAC, rbacPermissions });
270027
+ const defaultSubTab = canReadConfig
270028
+ ? GRADER_SUB_TABS.setup
270029
+ : canViewCriteria
270030
+ ? GRADER_SUB_TABS.rubric
270031
+ : GRADER_SUB_TABS.results;
270032
+ // With every grader view action denied, no sub-tab trigger renders — treat
270033
+ // it like a read denial rather than showing an empty shell (the default
270034
+ // tab's content would otherwise leak without its trigger).
270035
+ const nothingViewable = !canReadConfig && !canViewCriteria && !canViewResults;
269427
270036
  const showNoCriteriaWarning = enabled && hasConfig && !isCriteriaLoading && criteria.length === 0;
269428
270037
  const showNoConfigWarning = enabled && !isLoading && !hasConfig && !isForbidden;
269429
270038
  const warningMessage = showNoConfigWarning
@@ -269431,7 +270040,7 @@ function AgentGraderTab({ labels: labelsOverride, tenantKey: tenantKeyProp, ment
269431
270040
  : showNoCriteriaWarning
269432
270041
  ? labels.warnings.noCriteria
269433
270042
  : null;
269434
- return (jsxs(Fragment$1, { children: [jsx("div", { className: "flex h-[73px] flex-shrink-0 items-center border-b border-gray-200 bg-white p-4 lg:block", children: jsxs("div", { children: [jsx("h3", { className: "mb-1 text-base font-medium text-gray-900", children: labels.header.title }), jsx("p", { className: "text-xs text-gray-600", children: labels.header.description })] }) }), jsx("div", { className: "flex-1 space-y-4 p-3 lg:p-4", style: { overflowY: 'auto', overflowX: 'hidden' }, "data-testid": "grader-tab-body", children: isLoading ? (jsx("div", { className: "flex items-center justify-center py-12", "data-testid": "grader-tab-loading", children: jsx(Spinner, {}) })) : isForbidden ? (jsxs("div", { className: "flex flex-col items-center gap-2 rounded-lg border border-gray-200 bg-gray-50 px-4 py-10 text-center", "data-testid": "grader-tab-denied", children: [jsx(ShieldAlert, { className: "h-6 w-6 text-gray-400" }), jsx("p", { className: "text-sm font-medium text-gray-900", children: labels.denied.title }), jsx("p", { className: "max-w-sm text-xs text-gray-600", children: labels.denied.description })] })) : (jsxs(CapabilityGate, { title: labels.capability.title, description: labels.capability.description, offHint: labels.capability.offHint, enabled: enabled, onToggle: toggleGrading, disabled: isToggling, ariaLabel: labels.capability.title, toggleTestId: "grader-capability-toggle", children: [warningMessage && (jsxs("div", { className: "mb-4 flex items-start gap-2 rounded-lg border border-amber-200 bg-amber-50 p-3", "data-testid": "grader-misconfigured-warning", children: [jsx(TriangleAlert, { className: "mt-0.5 h-4 w-4 flex-shrink-0 text-amber-600" }), jsx("p", { className: "text-xs leading-relaxed text-amber-800", children: warningMessage })] })), jsxs(Tabs, { defaultValue: GRADER_SUB_TABS.setup, className: "w-full", children: [jsxs(TabsList, { "aria-label": labels.header.title, "data-testid": "grader-sub-tabs", children: [jsx(TabsTrigger, { value: GRADER_SUB_TABS.setup, "data-testid": "grader-sub-tab-setup", children: labels.subTabs.setup }), jsx(TabsTrigger, { value: GRADER_SUB_TABS.rubric, "data-testid": "grader-sub-tab-rubric", children: labels.subTabs.rubric })] }), jsx(TabsContent, { value: GRADER_SUB_TABS.setup, className: "space-y-4", children: jsx(SetupSection, { labels: labels.config, config: config, isSaving: isSavingConfig, onSave: saveConfig }) }), jsx(TabsContent, { value: GRADER_SUB_TABS.rubric, className: "space-y-4", children: jsx(RubricSection, { labels: labels.criteria, criteria: criteria, hasConfig: hasConfig, isLoading: isCriteriaLoading, isMutating: isMutatingCriteria, totalPoints: totalPoints, onAdd: addCriterion, onEdit: editCriterion, onDelete: removeCriterion }) })] })] })) })] }));
270043
+ return (jsxs(Fragment$1, { children: [jsx("div", { className: "flex h-[73px] flex-shrink-0 items-center border-b border-gray-200 bg-white p-4 lg:block", children: jsxs("div", { children: [jsx("h3", { className: "mb-1 text-base font-medium text-gray-900", children: labels.header.title }), jsx("p", { className: "text-xs text-gray-600", children: labels.header.description })] }) }), jsx("div", { className: "flex-1 space-y-4 p-3 lg:p-4", style: { overflowY: 'auto', overflowX: 'hidden' }, "data-testid": "grader-tab-body", children: isLoading ? (jsx("div", { className: "flex items-center justify-center py-12", "data-testid": "grader-tab-loading", children: jsx(Spinner, {}) })) : isForbidden || nothingViewable ? (jsxs("div", { className: "flex flex-col items-center gap-2 rounded-lg border border-gray-200 bg-gray-50 px-4 py-10 text-center", "data-testid": "grader-tab-denied", children: [jsx(ShieldAlert, { className: "h-6 w-6 text-gray-400" }), jsx("p", { className: "text-sm font-medium text-gray-900", children: labels.denied.title }), jsx("p", { className: "max-w-sm text-xs text-gray-600", children: labels.denied.description })] })) : (jsxs(CapabilityGate, { title: labels.capability.title, description: labels.capability.description, offHint: labels.capability.offHint, enabled: enabled, onToggle: toggleGrading, disabled: isToggling, ariaLabel: labels.capability.title, toggleTestId: "grader-capability-toggle", children: [warningMessage && (jsxs("div", { className: "mb-4 flex items-start gap-2 rounded-lg border border-amber-200 bg-amber-50 p-3", "data-testid": "grader-misconfigured-warning", children: [jsx(TriangleAlert, { className: "mt-0.5 h-4 w-4 flex-shrink-0 text-amber-600" }), jsx("p", { className: "text-xs leading-relaxed text-amber-800", children: warningMessage })] })), jsxs(Tabs, { defaultValue: defaultSubTab, className: "w-full", children: [jsxs(TabsList, { "aria-label": labels.header.title, "data-testid": "grader-sub-tabs", children: [canReadConfig && (jsx(TabsTrigger, { value: GRADER_SUB_TABS.setup, "data-testid": "grader-sub-tab-setup", children: labels.subTabs.setup })), canViewCriteria && (jsx(TabsTrigger, { value: GRADER_SUB_TABS.rubric, "data-testid": "grader-sub-tab-rubric", children: labels.subTabs.rubric })), canViewResults && (jsx(TabsTrigger, { value: GRADER_SUB_TABS.results, "data-testid": "grader-sub-tab-results", children: labels.subTabs.results }))] }), jsx(TabsContent, { value: GRADER_SUB_TABS.setup, className: "space-y-4", children: jsx(SetupSection, { labels: labels.config, config: config, isSaving: isSavingConfig, canSave: canSaveConfig, onSave: saveConfig }) }), jsx(TabsContent, { value: GRADER_SUB_TABS.rubric, className: "space-y-4", children: jsx(RubricSection, { labels: labels.criteria, criteria: criteria, hasConfig: hasConfig, isLoading: isCriteriaLoading, isMutating: isMutatingCriteria, totalPoints: totalPoints, canAdd: canAddCriterion, canEdit: canEditCriterion, canDelete: canDeleteCriterion, onAdd: addCriterion, onEdit: editCriterion, onDelete: removeCriterion }) }), jsx(TabsContent, { value: GRADER_SUB_TABS.results, className: "space-y-4", children: jsx(ResultsSection, { labels: labels.results, tenantKey: tenantKey, mentorId: mentorId, username: username, canOverride: canOverrideResults }) })] })] })) })] }));
269435
270044
  }
269436
270045
 
269437
270046
  function ApiKeyModal({ isOpen, onClose, apiKey, labels }) {