@iblai/iblai-js 2.17.0 → 2.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/web-containers/source/index.esm.js +1439 -293
- package/dist/web-containers/source/next/index.esm.js +1387 -358
- package/package.json +5 -5
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import React__default, { useRef, useEffect,
|
|
3
|
-
import { useDispatch, useSelector } from 'react-redux';
|
|
4
|
-
import { selectSessionId, selectActiveChatMessages, useCachedSessionId, chatActions, LOCAL_STORAGE_KEYS, TimeTracker, selectRbacPermissions, useCurrentTenant, canViewOtherUsersChatHistory, getInitials, useTenantMetadata, isPureWatcher, WithPermissions, canWriteField, useStripeUpgrade, openExternalUrl, CHAT_AREA_SIZE, isAlphaNumeric32, checkRbacPermission, getTimeAgo, REQUIRED_ACTIONS_FOR_GROUPS, getVisibleAnalyticsTabs, getUserName as getUserName$2, formatRelativeTime as formatRelativeTime$2, ANONYMOUS_USERNAME, combineCSVData, WATCHER_HIDDEN_REPORTS, canViewPlatformAuditLogs, redirectToAuthSpaJoinTenant, redirectToAuthSpa, getAuthSpaJoinUrl, useOS, 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, chatInputSliceActions, removeFile, WithFormPermissions, MENTOR_VISIBILITY } from '@iblai/web-utils';
|
|
2
|
+
import React__default, { useRef, useEffect, useMemo, useCallback, useState, createContext, useContext, forwardRef, createElement as createElement$1, useLayoutEffect, useReducer, useImperativeHandle, isValidElement, Children, PureComponent, cloneElement, Component, useId as useId$2, useDebugValue, lazy, Suspense } from 'react';
|
|
5
3
|
import * as dataLayer from '@iblai/data-layer';
|
|
6
|
-
import { useCreateSessionIdMutation, useTimeTrackingMutation, useGetUserMetadataQuery, useGetUserMetadataEdxQuery, useGetUserProfileSummaryQuery, useUpdateUserMetadataMutation, useUpdateUserMetadataEdxMutation, useUploadProfileImageMutation, useResetPasswordMutation, useSelfRetireMutation, useCreateUserInstitutionMutation, useGetUserInstitutionsQuery, useCreateUserEducationMutation, useUpdateUserEducationMutation, useDeleteUserEducationMutation, useGetUserEducationQuery, useCreateUserCompanyMutation, useGetUserCompaniesQuery, useCreateUserExperienceMutation, useUpdateUserExperienceMutation, useDeleteUserExperienceMutation, useGetUserExperienceQuery, useGetUserResumeQuery, useCreateUserResumeMutation, useGetMySubscriptionsQuery, useGetItemSubscriptionQuery, useCancelSubscriptionMutation, useGetLearnerDetailsQuery, useGetUserEnrolledCoursesQuery, useGetUserEnrolledProgramsQuery, useGetUserCatalogPathwaysQuery, useGetUsersAsAssertionsQuery, useGetUserEarnedSkillsQuery, useGetUserReportedSkillsQuery, useGetUserDesiredSkillsQuery, useCreateGlobalMemoryMutation, useUpdateGlobalMemoryMutation, useUpdateMentorMemoryMutation, useGetMemsearchStatusQuery, useGetUserMemorySettingsQuery, useUpdateUserMemorySettingsMutation, useGetGlobalMemoriesQuery, useGetAllMentorMemoriesQuery, useDeleteGlobalMemoryMutation, useDeleteMentorMemoryMutation, useGetAiSearchMentorsQuery, useGetUserChatHistoryReportsQuery, USER_CHAT_HISTORY_REPORT_ACTIVE_STATES, useCreateUserChatHistoryReportMutation, useLazyGetDownloadReportFromURLQuery, useGetUserChatHistoryReportStatusQuery, userChatHistoryApiSlice, USER_CHAT_HISTORY_QUERY_KEYS, useGetUserChatHistoryQuery, useGetUserChatHistoryFilterQuery, useGetMentorsQuery, useGetUserChatHistorySessionQuery, 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, useGetTenantMetadataQuery, useUpdateTenantMetadataMutation, useLazyGetTenantMetadataQuery, useDeleteApiKeyMutation, useGetApiKeyQuery, useGetApiKeyFieldPermissionsQuery, useUpdateApiKeyMutation, useGetApiKeysQuery, unwrapApiTokenList, useCreateApiKeyMutation, useCreateLLMCredentialMutation, useGetCredentialsSchemaQuery, useGetMaskedLLMCredentialsQuery, useGetLlmsQuery, useDeleteIntegrationCredentialMutation, useDeleteCredentialMutation, useCreateIntegrationCredentialMutation, useGetIntegrationCredentialsSchemaQuery, useGetMaskedIntegrationCredentialsQuery, useGetAccountBillingInfoQuery, useUpdateAutoRechargeInfoMutation, useTriggerAutoRechargeMutation, useGetAgentSpendCapQuery, useGetTenantSpendCapQuery, useListAgentUserSpendCapsQuery, useUpsertAgentSpendCapMutation, useDeleteAgentSpendCapMutation, useUpsertTenantSpendCapMutation, useDeleteTenantSpendCapMutation, useUpsertUserSpendCapMutation, useDeleteUserSpendCapMutation, useGetLlmUsageMetricsQuery, useListAgentSpendCapsQuery, useGetCreditTransactionsQuery, useCreateStripeCustomerPortalMutation, useSetPlatformConfigurationsMutation, useGetPlatformConfigurationsQuery, useUpdatePlatformMembershipMutation, useGetPlatformMembershipQuery, useGetCustomDomainsQuery, useCreateCustomDomainMutation, useDeleteCustomDomainMutation, useGetStudentMentorCreationStatusQuery, useSetStudentMentorCreationStatusMutation, coreApiSlice, recommendationPromptTypeEnum, useGetRecommendedPromptsListQuery, useCreateRecommendedPromptMutation, useUpdateRecommendedPromptMutation, useDeleteRecommendedPromptMutation, useLazyGetPublicPlatformImageAssetFileUrlQuery, useCreatePlatformImageAssetMutation, useGetProviderConfigQuery, useCreateProviderConfigMutation, useDeleteProviderConfigMutation, useGetExternalMappingQuery, useGetCredentialsListQuery, useCreateExternalMappingMutation, useDeleteExternalMappingMutation, useGetMemsearchConfigQuery, useUpdateMemsearchConfigMutation, useGetStripeConnectStatusQuery, useStartStripeConnectOnboardingMutation, useLazyGetStripeConnectDashboardQuery, useListPaywallsQuery, useListPricesQuery, useCreatePriceMutation, useUpdatePriceMutation, useDeletePriceMutation, useGetPaywallConfigQuery, useEnablePaywallMutation, useUpdatePaywallMutation, useGetMentorMemoriesListQuery, useGetMemoryCategoriesAdminQuery, useCreateMentorMemoryMutation, useGetNotificationsCountQuery, useLazyGetNotificationsQuery, useMarkAllAsReadMutation, useCreateNotificationPreviewMutation, useSendNotificationMutation, USER_PROGRESS_DATA_POINTS, useResetTemplateMutation, useSendTestTemplateEmailMutation, useUpdateTemplateMutation, useGetTemplateDetailsQuery, USER_PROGRESS_SUMMARY_TYPE, useGetTemplatesQuery, useLazyGetTemplateDetailsQuery, useToggleTemplateMutation, useGetLlmUsageTracesQuery, useGetLlmUsageObservationsQuery, useGetTopicsStatsQuery, useGetUsersStatsQuery, useGetSessionStatsQuery, useGetTopicsDetailsStatsQuery, useGetTranscriptsConversationHeadlineQuery, useGetAccessTimeHeatmapQuery, useGetUserDetailsStatsQuery, useGetAverageRatingQuery, useGetModelCostsQuery, useGetPerUserCostsQuery, useGetTenantCostQuery, useGetAgentCostQuery, useGetTranscriptsMessagesDetailsQuery, useGetTranscriptsMessagesQuery, useGetReportDetailQuery, useGetMentorPublicSettingsQuery, useGetReportsQuery, useCreateReportMutation, useGetContentAnalyticsQuery, useGetContentAnalyticsDetailsQuery, useGetRevenueQuery, useListSubscribersQuery, useGetAuditLogsQuery, useGetPlatformAuditLogsQuery, PLATFORM_AUDIT_EVENT_TYPES, PLATFORM_AUDIT_ACTION_CODES, useGetMentorMemoriesQuery, useLazyGetCourseMetaDataQuery, useLazyGetCourseCompletionOutlinesQuery, useLazyGetCourseEligibilityQuery, useLazyGetUserEnrolledCoursesQuery, useLazyGetUserAssignedCoursesQuery, useLazyGetUserCredentialsQuery, useLazyGetOverTimeActivityQuery, useLazyGetCatalogSearchQuery, useCreateOrUpdateUserReportedSkillMutation, useCreateOrUpdateUserDesiredSkillMutation, useLazyGetPathwayListQuery, useLazyGetUserAssignedPathwaysQuery, useLazyGetUserEnrolledPathwaysQuery, useLazyGetPathwayCompletionQuery, useLazyGetProgramListQuery, useLazyGetProgramCompletionQuery, useLazyGetUserEnrolledProgramsQuery, useLazyGetAssignedProgramsQuery, useLazyGetUserSkillsPointsQuery, useLazyGetUserReportedSkillsQuery, useLazyGetUserDesiredSkillsQuery, useLazyGetUserCatalogPathwaysQuery, useLazyGetPerLearnerInfoQuery, useLazyGetEdxSSOTokenQuery, useCreateCourseEnrollmentMutation, useCreateStripeCheckoutSessionMutation, useLazyGetCourseProgressQuery, useLazyGetCourseCompletionQuery, useLazyGetPersonnalizedSearchQuery, useUpdateExamAttemptMutation, useStartExamMutation, useLazyGetExamInfoQuery, useGetMentorSettingsQuery, useEditMentorMutation, useGetClawMentorConfigQuery, useGetClawInstancesQuery, useGetAgentConfigQuery, useUpdateClawMentorConfigMutation, useCreateClawMentorConfigMutation, useDeleteClawMentorConfigMutation, usePushClawConfigMutation, useCreateClawInstanceMutation, useDeleteClawInstanceMutation, useUpdateAgentConfigMutation, useHealthCheckClawInstanceMutation, useTestConnectivityClawInstanceMutation, useUpdateClawInstanceMutation, useGetAgentSkillResourcesQuery, useCreateAgentSkillResourceMutation, useUpdateAgentSkillResourceMutation, useUploadAgentSkillResourceAssetMutation, useDeleteAgentSkillResourceMutation, useGetMentorSkillAssignmentsQuery, useGetAgentSkillsQuery, useCreateMentorSkillAssignmentMutation, useUpdateMentorSkillAssignmentMutation, useDeleteMentorSkillAssignmentMutation, useCreateAgentSkillMutation, useUpdateAgentSkillMutation, useDeleteAgentSkillMutation, filterSlashSkills, useGetMentorSkillAssignmentsInfiniteQuery, MENTOR_SKILL_ASSIGNMENTS_PAGE_SIZE, useCreateCheckoutMutation, useGetUserProjectsQuery, useUpdateUserProjectMutation, useGetTrainingDocumentsQuery, useGetVectorDocumentsQuery, useLazyGetConnectedServiceAuthUrlQuery, useCreateUserProjectMutation, useDeleteUserProjectMutation, useGetUserProjectDetailsQuery, useEditTrainingDocumentMutation, useAddTrainingDocumentMutation, useLazyGetCredentialsQuery, useGetMentorCategoriesQuery, useCreateMentorMutation, useUpdateUserPlatformMetadataMutation, useGetApplicationStatusQuery, useListOwnApplicationsQuery, useGetApplicationFormQuery, useWithdrawApplicationMutation, useRenewApplicationMutation, useCreateApplicationDraftMutation, useSubmitApplicationMutation, useUpdateApplicationMutation, useUploadApplicationAttachmentMutation, useDeleteApplicationAttachmentMutation, useCreateMemoryCategoryMutation, useUpdateMemoryCategoryMutation, useDeleteMemoryCategoryMutation, useGetPromptCategoriesQuery, useCreatePromptMutation, useDeletePromptMutation, useGetPromptsSearchQuery, useUpdatePromptMutation, useDeleteTrainingDocumentMutation, useGetTrainingDocumentRetrainScheduleQuery, useCreateTrainingDocumentRetrainScheduleMutation } from '@iblai/data-layer';
|
|
4
|
+
import { useGetLlmsQuery, useCreateSessionIdMutation, useTimeTrackingMutation, useGetUserMetadataQuery, useGetUserMetadataEdxQuery, useGetUserProfileSummaryQuery, useUpdateUserMetadataMutation, useUpdateUserMetadataEdxMutation, useUploadProfileImageMutation, useResetPasswordMutation, useSelfRetireMutation, useCreateUserInstitutionMutation, useGetUserInstitutionsQuery, useCreateUserEducationMutation, useUpdateUserEducationMutation, useDeleteUserEducationMutation, useGetUserEducationQuery, useCreateUserCompanyMutation, useGetUserCompaniesQuery, useCreateUserExperienceMutation, useUpdateUserExperienceMutation, useDeleteUserExperienceMutation, useGetUserExperienceQuery, useGetUserResumeQuery, useCreateUserResumeMutation, useGetMySubscriptionsQuery, useGetItemSubscriptionQuery, useCancelSubscriptionMutation, useGetLearnerDetailsQuery, useGetUserEnrolledCoursesQuery, useGetUserEnrolledProgramsQuery, useGetUserCatalogPathwaysQuery, useGetUsersAsAssertionsQuery, useGetUserEarnedSkillsQuery, useGetUserReportedSkillsQuery, useGetUserDesiredSkillsQuery, useCreateGlobalMemoryMutation, useUpdateGlobalMemoryMutation, useUpdateMentorMemoryMutation, useGetMemsearchStatusQuery, useGetUserMemorySettingsQuery, useUpdateUserMemorySettingsMutation, useGetGlobalMemoriesQuery, useGetAllMentorMemoriesQuery, useDeleteGlobalMemoryMutation, useDeleteMentorMemoryMutation, useGetAiSearchMentorsQuery, useGetUserChatHistoryReportsQuery, USER_CHAT_HISTORY_REPORT_ACTIVE_STATES, useCreateUserChatHistoryReportMutation, useLazyGetDownloadReportFromURLQuery, useGetUserChatHistoryReportStatusQuery, userChatHistoryApiSlice, USER_CHAT_HISTORY_QUERY_KEYS, useGetUserChatHistoryQuery, useGetUserChatHistoryFilterQuery, useGetMentorsQuery, useGetUserChatHistorySessionQuery, useInviteUserMutation, usePlatformInvitationsQuery, useCreateCatalogInvitationCourseBulkMutation, useGetCatalogInvitationsCourseQuery, useLazyPlatformUsersQuery, useLazyPlatformUserGroupsQuery, useGetPersonnalizedSearchQuery, useCreateCatalogInvitationProgramBulkMutation, useGetCatalogInvitationsProgramQuery, useGetVectorDocumentsQuery, useUpdateUserRoleMutation, useUpdateUserStatusMutation, useUpdatePlatformUserRoleWithPoliciesMutation, usePlatformUsersQuery, useGetAccessibleUsersQuery, isPoliciesResponse, platformApiSlice, featureTags, useLazyGetRbacTeamsAccessListQuery, useCreateRbacTeamsAccessMutation, useGetRbacGroupsQuery, usePlatformUserGroupsQuery, useCreateRbacGroupMutation, useUpdateRbacGroupMutation, useDeleteRbacGroupMutation, useCreatePlatformUserGroupMutation, useUpdatePlatformUserGroupMutation, useDeletePlatformUserGroupMutation, useGetRbacGroupDetailsQuery, useGetPlatformUserGroupDetailsQuery, useGetRbacPermissionsMutation, useGetRbacRolesQuery, useCreateRbacRoleMutation, useUpdateRbacRoleMutation, useDeleteRbacRoleMutation, useGetRbacRoleDetailsQuery, useGetRbacActionsDefinitionQuery, useGetRbacResourceDiscoveryQuery, useGetRbacResourceListQuery, useGetRbacPoliciesQuery, useCreateRbacPolicyMutation, useUpdateRbacPolicyMutation, useDeleteRbacPolicyMutation, useGetRbacPolicyDetailsQuery, useGetWatchedGroupsQuery, useCreateWatchedGroupMutation, useUpdateWatchedGroupMutation, useDeleteWatchedGroupMutation, useAddWatchedUserMutation, useRemoveWatchedUserMutation, useAddWatcherMutation, useUpdateWatcherMutation, useDeleteWatcherMutation, useGetWatchedUsersQuery, useGetWatchersQuery, WATCHER_NOTIFICATION_EVENTS, WATCHER_NOTIFICATION_EVENT_LABELS, useGetApplicationFormsQuery, useGetApplicationFormDetailQuery, useCreateApplicationFormMutation, useUpdateApplicationFormMutation, useGetApplicationAdminDetailQuery, useInviteApplicationCandidateMutation, useLazyGetApplicationAttachmentFileQuery, useCreateApplicationWaiverMutation, useDeleteApplicationWaiverMutation, useSubmitApplicationOverrideMutation, useUpdateApplicationPlacementMutation, useDeleteApplicationCourseAssignmentMutation, useCreateApplicationNoteMutation, useUpdateApplicationNoteMutation, useDeleteApplicationNoteMutation, useTransitionApplicationMutation, useLinkApplicationCandidateMutation, useCreateApplicationPlacementsMutation, useGetCustomMentorsQuery, useCreateApplicationCourseAssignmentsMutation, useGetApplicationBlocksQuery, useDeleteApplicationBlockMutation, useGetApplicationsPipelineStatsQuery, useGetApplicationsPipelineQuery, useGetTenantMetadataQuery, useUpdateTenantMetadataMutation, useLazyGetTenantMetadataQuery, useDeleteApiKeyMutation, useGetApiKeyQuery, useGetApiKeyFieldPermissionsQuery, useUpdateApiKeyMutation, useGetApiKeysQuery, unwrapApiTokenList, useCreateApiKeyMutation, useCreateLLMCredentialMutation, useGetCredentialsSchemaQuery, useGetMaskedLLMCredentialsQuery, useDeleteIntegrationCredentialMutation, useDeleteCredentialMutation, useCreateIntegrationCredentialMutation, useGetIntegrationCredentialsSchemaQuery, useGetMaskedIntegrationCredentialsQuery, useGetAccountBillingInfoQuery, useUpdateAutoRechargeInfoMutation, useTriggerAutoRechargeMutation, useGetAgentSpendCapQuery, useGetTenantSpendCapQuery, useListAgentUserSpendCapsQuery, useUpsertAgentSpendCapMutation, useDeleteAgentSpendCapMutation, useUpsertTenantSpendCapMutation, useDeleteTenantSpendCapMutation, useUpsertUserSpendCapMutation, useDeleteUserSpendCapMutation, useGetLlmUsageMetricsQuery, useListAgentSpendCapsQuery, useGetCreditTransactionsQuery, useCreateStripeCustomerPortalMutation, useSetPlatformConfigurationsMutation, useGetPlatformConfigurationsQuery, useUpdatePlatformMembershipMutation, useGetPlatformMembershipQuery, useGetCustomDomainsQuery, useCreateCustomDomainMutation, useDeleteCustomDomainMutation, useGetStudentMentorCreationStatusQuery, useSetStudentMentorCreationStatusMutation, coreApiSlice, recommendationPromptTypeEnum, useGetRecommendedPromptsListQuery, useCreateRecommendedPromptMutation, useUpdateRecommendedPromptMutation, useDeleteRecommendedPromptMutation, useLazyGetPublicPlatformImageAssetFileUrlQuery, useCreatePlatformImageAssetMutation, useGetProviderConfigQuery, useCreateProviderConfigMutation, useDeleteProviderConfigMutation, useGetExternalMappingQuery, useGetCredentialsListQuery, useCreateExternalMappingMutation, useDeleteExternalMappingMutation, useGetMemsearchConfigQuery, useUpdateMemsearchConfigMutation, useGetStripeConnectStatusQuery, useStartStripeConnectOnboardingMutation, useLazyGetStripeConnectDashboardQuery, useListPaywallsQuery, useListPricesQuery, useCreatePriceMutation, useUpdatePriceMutation, useDeletePriceMutation, useGetPaywallConfigQuery, useEnablePaywallMutation, useUpdatePaywallMutation, useGetMentorMemoriesListQuery, useGetMemoryCategoriesAdminQuery, useCreateMentorMemoryMutation, useGetNotificationsCountQuery, useLazyGetNotificationsQuery, useMarkAllAsReadMutation, useCreateNotificationPreviewMutation, useSendNotificationMutation, USER_PROGRESS_DATA_POINTS, useResetTemplateMutation, useSendTestTemplateEmailMutation, useUpdateTemplateMutation, useGetTemplateDetailsQuery, USER_PROGRESS_SUMMARY_TYPE, useGetTemplatesQuery, useLazyGetTemplateDetailsQuery, useToggleTemplateMutation, useGetLlmUsageTracesQuery, useGetLlmUsageObservationsQuery, useGetTopicsStatsQuery, useGetUsersStatsQuery, useGetSessionStatsQuery, useGetTopicsDetailsStatsQuery, useGetTranscriptsConversationHeadlineQuery, useGetAccessTimeHeatmapQuery, useGetUserDetailsStatsQuery, useGetAverageRatingQuery, useGetModelCostsQuery, useGetPerUserCostsQuery, useGetTenantCostQuery, useGetAgentCostQuery, useGetTranscriptsMessagesDetailsQuery, useGetTranscriptsMessagesQuery, useGetReportDetailQuery, useGetMentorPublicSettingsQuery, useGetReportsQuery, useCreateReportMutation, useGetContentAnalyticsQuery, useGetContentAnalyticsDetailsQuery, useGetRevenueQuery, useListSubscribersQuery, useGetAuditLogsQuery, useGetPlatformAuditLogsQuery, PLATFORM_AUDIT_EVENT_TYPES, PLATFORM_AUDIT_ACTION_CODES, useGetMentorMemoriesQuery, useLazyGetCourseMetaDataQuery, useLazyGetCourseCompletionOutlinesQuery, useLazyGetCourseEligibilityQuery, useLazyGetUserEnrolledCoursesQuery, useLazyGetUserAssignedCoursesQuery, useLazyGetUserCredentialsQuery, useLazyGetOverTimeActivityQuery, useLazyGetCatalogSearchQuery, useCreateOrUpdateUserReportedSkillMutation, useCreateOrUpdateUserDesiredSkillMutation, useLazyGetPathwayListQuery, useLazyGetUserAssignedPathwaysQuery, useLazyGetUserEnrolledPathwaysQuery, useLazyGetPathwayCompletionQuery, useLazyGetProgramListQuery, useLazyGetProgramCompletionQuery, useLazyGetUserEnrolledProgramsQuery, useLazyGetAssignedProgramsQuery, useLazyGetUserSkillsPointsQuery, useLazyGetUserReportedSkillsQuery, useLazyGetUserDesiredSkillsQuery, useLazyGetUserCatalogPathwaysQuery, useLazyGetPerLearnerInfoQuery, useLazyGetEdxSSOTokenQuery, useCreateCourseEnrollmentMutation, useCreateStripeCheckoutSessionMutation, useLazyGetCourseProgressQuery, useLazyGetCourseCompletionQuery, useLazyGetPersonnalizedSearchQuery, useUpdateExamAttemptMutation, useStartExamMutation, useLazyGetExamInfoQuery, useGetMentorSettingsQuery, useEditMentorMutation, useGetClawMentorConfigQuery, useGetClawInstancesQuery, useGetAgentConfigQuery, useUpdateClawMentorConfigMutation, useCreateClawMentorConfigMutation, useDeleteClawMentorConfigMutation, usePushClawConfigMutation, useCreateClawInstanceMutation, useDeleteClawInstanceMutation, useUpdateAgentConfigMutation, useHealthCheckClawInstanceMutation, useTestConnectivityClawInstanceMutation, useUpdateClawInstanceMutation, useGetAgentSkillResourcesQuery, useCreateAgentSkillResourceMutation, useUpdateAgentSkillResourceMutation, useUploadAgentSkillResourceAssetMutation, useDeleteAgentSkillResourceMutation, useGetMentorSkillAssignmentsQuery, useGetAgentSkillsQuery, useCreateMentorSkillAssignmentMutation, useUpdateMentorSkillAssignmentMutation, useDeleteMentorSkillAssignmentMutation, useCreateAgentSkillMutation, useUpdateAgentSkillMutation, useDeleteAgentSkillMutation, filterSlashSkills, useGetMentorSkillAssignmentsInfiniteQuery, MENTOR_SKILL_ASSIGNMENTS_PAGE_SIZE, useCreateCheckoutMutation, useGetUserProjectsQuery, useUpdateUserProjectMutation, useGetTrainingDocumentsQuery, useLazyGetConnectedServiceAuthUrlQuery, useCreateUserProjectMutation, useDeleteUserProjectMutation, useGetUserProjectDetailsQuery, useEditTrainingDocumentMutation, useAddTrainingDocumentMutation, useLazyGetCredentialsQuery, useGetMentorCategoriesQuery, useCreateMentorMutation, useUpdateUserPlatformMetadataMutation, useGetApplicationStatusQuery, useListOwnApplicationsQuery, useGetApplicationFormQuery, useWithdrawApplicationMutation, useRenewApplicationMutation, useCreateApplicationDraftMutation, useSubmitApplicationMutation, useUpdateApplicationMutation, useUploadApplicationAttachmentMutation, useDeleteApplicationAttachmentMutation, useCreateMemoryCategoryMutation, useUpdateMemoryCategoryMutation, useDeleteMemoryCategoryMutation, useGetPromptCategoriesQuery, useCreatePromptMutation, useDeletePromptMutation, useGetPromptsSearchQuery, useUpdatePromptMutation, useDeleteTrainingDocumentMutation, useGetTrainingDocumentRetrainScheduleQuery, useCreateTrainingDocumentRetrainScheduleMutation } from '@iblai/data-layer';
|
|
5
|
+
import { useDispatch, useSelector } from 'react-redux';
|
|
6
|
+
import { selectSessionId, selectActiveChatMessages, useCachedSessionId, chatActions, LOCAL_STORAGE_KEYS, TimeTracker, selectRbacPermissions, useCurrentTenant, canViewOtherUsersChatHistory, getInitials, useTenantMetadata, useUsername, selectStreaming, isLoggedIn, TOOL_NAME_MAP, WRITE_TODOS_TOOL, isPureWatcher, WithPermissions, canWriteField, useStripeUpgrade, openExternalUrl, CHAT_AREA_SIZE, isAlphaNumeric32, checkRbacPermission, getTimeAgo, REQUIRED_ACTIONS_FOR_GROUPS, getVisibleAnalyticsTabs, getUserName as getUserName$2, formatRelativeTime as formatRelativeTime$2, ANONYMOUS_USERNAME, combineCSVData, WATCHER_HIDDEN_REPORTS, canViewPlatformAuditLogs, redirectToAuthSpaJoinTenant, redirectToAuthSpa, getAuthSpaJoinUrl, useOS, selectNumberOfActiveChatMessages, TOOLS, hasRemoteAiConfig, isSafariBrowser, useShowAttachment, useShowVoiceCall, useShowVoiceRecorder, useMentorSettings, selectShowingSharedChat, useShowFreeTrialDialog, useEmbedMode, chatInputSliceSelectors, useResponsive, useAccessingPublicRoute, useVisitingTenant, useModelFileUploadCapabilities, useChatFileUpload, useVoiceChat, selectAttachedFiles, MENTOR_CHAT_DOCUMENTS_EXTENSIONS, chatInputSliceActions, removeFile, WithFormPermissions, MENTOR_VISIBILITY } from '@iblai/web-utils';
|
|
7
7
|
import { toast } from 'sonner';
|
|
8
8
|
import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
9
9
|
import * as ReactDOM from 'react-dom';
|
|
@@ -11,13 +11,13 @@ import ReactDOM__default from 'react-dom';
|
|
|
11
11
|
import { z } from 'zod';
|
|
12
12
|
import { RemoveScroll } from 'react-remove-scroll';
|
|
13
13
|
import { skipToken } from '@reduxjs/toolkit/query';
|
|
14
|
+
import Link$2 from 'next/link';
|
|
15
|
+
import { useParams, useSearchParams, useRouter, usePathname } from 'next/navigation';
|
|
14
16
|
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
15
17
|
import { createDialogScope } from '@radix-ui/react-dialog';
|
|
16
18
|
import dynamic from 'next/dynamic';
|
|
17
19
|
import { NotificationSourceTypeEnum, StateEnum, MentorVisibilityEnum, PromptVisibilityEnum } from '@iblai/iblai-api';
|
|
18
|
-
import { useSearchParams, useRouter, usePathname, useParams } from 'next/navigation';
|
|
19
20
|
import Image$4 from 'next/image';
|
|
20
|
-
import Link$2 from 'next/link';
|
|
21
21
|
import Script from 'next/script';
|
|
22
22
|
|
|
23
23
|
function useIframeMessageHandler({ handlers, allowedOrigins, defaultHandler, }) {
|
|
@@ -55,6 +55,218 @@ function useIframeMessageHandler({ handlers, allowedOrigins, defaultHandler, })
|
|
|
55
55
|
}, [allowedOrigins]);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
// Model wire keys whose raw form is not presentable, keyed lowercased and
|
|
59
|
+
// alphanumerics-only.
|
|
60
|
+
const IBL_AI_DISPLAY_NAME = 'ibl.ai';
|
|
61
|
+
const MODEL_DISPLAY_NAME_BY_KEY = {
|
|
62
|
+
iblai: IBL_AI_DISPLAY_NAME,
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* The label to show for a model when only its wire key is known.
|
|
66
|
+
*
|
|
67
|
+
* The LLM picker gets a `display_name` per model straight from the API, but
|
|
68
|
+
* mentor settings and transcripts persist only `llm_name` — a wire key — so
|
|
69
|
+
* surfaces that read from those have no label to fall back on and would
|
|
70
|
+
* render `iblai`. Most keys are already presentable (`gpt-4.1`), so this maps
|
|
71
|
+
* only the ones that are not and passes everything else through untouched.
|
|
72
|
+
*/
|
|
73
|
+
function getLLMModelDisplayName(llmName) {
|
|
74
|
+
var _a;
|
|
75
|
+
const raw = llmName !== null && llmName !== void 0 ? llmName : '';
|
|
76
|
+
const normalized = raw.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
77
|
+
// ibl.ai keys are the brand followed by an optional variant — `iblai`,
|
|
78
|
+
// `iblai-pro`, `iblai-fast`, `IBL AI Pro`. Rebuild the label the model
|
|
79
|
+
// picker gets from the API (`ibl.ai Pro`) rather than collapsing every
|
|
80
|
+
// variant onto a bare `ibl.ai`, which would disagree with the picker.
|
|
81
|
+
const brand = /^(iblai|ibl)(.*)$/.exec(normalized);
|
|
82
|
+
const leadsWithBrand = brand &&
|
|
83
|
+
(brand[1] === 'iblai' ||
|
|
84
|
+
raw
|
|
85
|
+
.toLowerCase()
|
|
86
|
+
.split(/[^a-z0-9]+/)
|
|
87
|
+
.filter(Boolean)[0] === 'ibl');
|
|
88
|
+
if (leadsWithBrand) {
|
|
89
|
+
const variant = brand[2];
|
|
90
|
+
if (!variant)
|
|
91
|
+
return IBL_AI_DISPLAY_NAME;
|
|
92
|
+
// `ai` is part of the brand when the key spells it out (`ibl-ai-pro`).
|
|
93
|
+
const suffix = variant.startsWith('ai') && brand[1] === 'ibl' ? variant.slice(2) : variant;
|
|
94
|
+
if (!suffix)
|
|
95
|
+
return IBL_AI_DISPLAY_NAME;
|
|
96
|
+
return `${IBL_AI_DISPLAY_NAME} ${suffix.charAt(0).toUpperCase()}${suffix.slice(1)}`;
|
|
97
|
+
}
|
|
98
|
+
return (_a = MODEL_DISPLAY_NAME_BY_KEY[normalized]) !== null && _a !== void 0 ? _a : raw;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Loose key for matching a model across spellings: lower-case, alphanumerics only. */
|
|
102
|
+
const modelKey = (value) => (value !== null && value !== void 0 ? value : '').toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
103
|
+
/**
|
|
104
|
+
* Model families → the provider keys the catalogue may list them under, for
|
|
105
|
+
* a model the catalogue does not name (a dated or "-latest" wire key, or a
|
|
106
|
+
* model the tenant enabled elsewhere). First key present in the catalogue
|
|
107
|
+
* wins; hosted variants (Azure, Bedrock, Groq) come after the vendor.
|
|
108
|
+
*/
|
|
109
|
+
const MODEL_FAMILY_PROVIDERS = [
|
|
110
|
+
[/^(gpt|o[1-9]|chatgpt|davinci|text-embedding)/, ['openai', 'azure_openai', 'azure']],
|
|
111
|
+
[/^claude/, ['anthropic', 'bedrock']],
|
|
112
|
+
[/^(gemini|gemma|palm)/, ['google', 'vertex', 'vertexai', 'gemini']],
|
|
113
|
+
[/^(llama|meta)/, ['llama', 'meta', 'bedrock', 'groq']],
|
|
114
|
+
[/^(mistral|mixtral|codestral)/, ['mistral']],
|
|
115
|
+
[/^deepseek/, ['deepseek']],
|
|
116
|
+
[/^grok/, ['xai', 'grok']],
|
|
117
|
+
[/^(command|aya)/, ['cohere']],
|
|
118
|
+
[/^qwen/, ['qwen', 'alibaba']],
|
|
119
|
+
[/^(nova|titan)/, ['bedrock', 'amazon']],
|
|
120
|
+
];
|
|
121
|
+
/** Provider keys a model of this family is listed under, in order of preference. */
|
|
122
|
+
function inferProviderKeysFromModel(model) {
|
|
123
|
+
const key = modelKey(model);
|
|
124
|
+
if (!key)
|
|
125
|
+
return [];
|
|
126
|
+
for (const [pattern, providers] of MODEL_FAMILY_PROVIDERS) {
|
|
127
|
+
if (pattern.test(key))
|
|
128
|
+
return providers;
|
|
129
|
+
}
|
|
130
|
+
return [];
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* A resolver from a provider key (the `llm_provider` mentor settings persist,
|
|
134
|
+
* e.g. `openai`) to the name and logo the backend publishes for it. A second,
|
|
135
|
+
* optional model key finds the provider whose `chat_models` list it, for
|
|
136
|
+
* payloads that name only the model (analytics transcript rows).
|
|
137
|
+
*
|
|
138
|
+
* Provider naming is backend-owned: the mentor-llms catalogue carries each
|
|
139
|
+
* provider's `logo` (and `display_name` where the API supplies one), so this
|
|
140
|
+
* reads the same RTK Query cache entry the LLM tab and model picker fill —
|
|
141
|
+
* matched on `name`. A key the catalogue does not list (the catalogue is
|
|
142
|
+
* still loading, or an on-device provider that has no backend row) resolves
|
|
143
|
+
* to the raw key and no logo, so callers degrade to plain text.
|
|
144
|
+
*
|
|
145
|
+
* Returns a function rather than a value so list renderers (a mentors table,
|
|
146
|
+
* a facet dropdown) can resolve many keys from one subscription.
|
|
147
|
+
*/
|
|
148
|
+
function useLlmProviderCatalogue({ org, userId, mentorId }) {
|
|
149
|
+
const skip = !org || !userId || !mentorId;
|
|
150
|
+
const { data: providers } = useGetLlmsQuery({
|
|
151
|
+
org: org !== null && org !== void 0 ? org : '',
|
|
152
|
+
// @ts-expect-error - userId is not in the generated query args but the endpoint scopes by it
|
|
153
|
+
userId: userId !== null && userId !== void 0 ? userId : '',
|
|
154
|
+
mentorId: mentorId !== null && mentorId !== void 0 ? mentorId : '',
|
|
155
|
+
}, { skip });
|
|
156
|
+
// Indexed once per catalogue load so list renderers resolve each key in
|
|
157
|
+
// O(1). First row wins on a duplicate name, as `Array.find` would.
|
|
158
|
+
const rowsByName = useMemo(() => {
|
|
159
|
+
const byName = new Map();
|
|
160
|
+
if (!Array.isArray(providers))
|
|
161
|
+
return byName;
|
|
162
|
+
for (const row of providers) {
|
|
163
|
+
if ((row === null || row === void 0 ? void 0 : row.name) && !byName.has(row.name))
|
|
164
|
+
byName.set(row.name, row);
|
|
165
|
+
}
|
|
166
|
+
return byName;
|
|
167
|
+
}, [providers]);
|
|
168
|
+
// Model key → the provider row listing it. Keyed loosely (see `modelKey`):
|
|
169
|
+
// transcripts persist the model as it was displayed ("GPT-5.2") while the
|
|
170
|
+
// catalogue lists the wire key ("gpt-5.2"), so both spellings, and the
|
|
171
|
+
// display name, must find the row.
|
|
172
|
+
const rowsByModel = useMemo(() => {
|
|
173
|
+
var _a;
|
|
174
|
+
const byModel = new Map();
|
|
175
|
+
for (const row of rowsByName.values()) {
|
|
176
|
+
for (const model of (_a = row.chat_models) !== null && _a !== void 0 ? _a : []) {
|
|
177
|
+
for (const candidate of [model === null || model === void 0 ? void 0 : model.llm_name, model === null || model === void 0 ? void 0 : model.display_name]) {
|
|
178
|
+
const key = modelKey(candidate);
|
|
179
|
+
if (key && !byModel.has(key))
|
|
180
|
+
byModel.set(key, row);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return byModel;
|
|
185
|
+
}, [rowsByName]);
|
|
186
|
+
// Provider rows keyed loosely by name and display name ("OpenAI" → openai).
|
|
187
|
+
const rowsByLooseName = useMemo(() => {
|
|
188
|
+
const byLoose = new Map();
|
|
189
|
+
for (const row of rowsByName.values()) {
|
|
190
|
+
for (const candidate of [row.name, row.display_name]) {
|
|
191
|
+
const key = modelKey(candidate);
|
|
192
|
+
if (key && !byLoose.has(key))
|
|
193
|
+
byLoose.set(key, row);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return byLoose;
|
|
197
|
+
}, [rowsByName]);
|
|
198
|
+
const rowForModel = useCallback((llmName) => {
|
|
199
|
+
var _a;
|
|
200
|
+
const wanted = modelKey(llmName);
|
|
201
|
+
if (!wanted)
|
|
202
|
+
return undefined;
|
|
203
|
+
const exact = rowsByModel.get(wanted);
|
|
204
|
+
if (exact)
|
|
205
|
+
return exact;
|
|
206
|
+
// A dated or "-latest" wire key ("gpt-5.2-2026-03-01") still names
|
|
207
|
+
// the family the catalogue lists ("gpt-5.2"), and vice versa.
|
|
208
|
+
for (const [listed, row] of rowsByModel) {
|
|
209
|
+
if (listed.startsWith(wanted) || wanted.startsWith(listed))
|
|
210
|
+
return row;
|
|
211
|
+
}
|
|
212
|
+
for (const provider of inferProviderKeysFromModel(llmName)) {
|
|
213
|
+
const row = (_a = rowsByName.get(provider)) !== null && _a !== void 0 ? _a : rowsByLooseName.get(modelKey(provider));
|
|
214
|
+
if (row)
|
|
215
|
+
return row;
|
|
216
|
+
}
|
|
217
|
+
return undefined;
|
|
218
|
+
}, [rowsByModel, rowsByName, rowsByLooseName]);
|
|
219
|
+
return useCallback((llmProvider, llmName) => {
|
|
220
|
+
var _a, _b, _c, _d, _e;
|
|
221
|
+
const key = llmProvider !== null && llmProvider !== void 0 ? llmProvider : '';
|
|
222
|
+
const row = (_c = (_b = (_a = rowsByName.get(key)) !== null && _a !== void 0 ? _a : rowsByName.get(key.toLowerCase())) !== null && _b !== void 0 ? _b : rowsByLooseName.get(modelKey(key))) !== null && _c !== void 0 ? _c : rowForModel(llmName);
|
|
223
|
+
return {
|
|
224
|
+
logo: (row === null || row === void 0 ? void 0 : row.logo) || null,
|
|
225
|
+
displayName: ((_d = row === null || row === void 0 ? void 0 : row.display_name) === null || _d === void 0 ? void 0 : _d.trim()) || ((_e = row === null || row === void 0 ? void 0 : row.name) === null || _e === void 0 ? void 0 : _e.trim()) || key,
|
|
226
|
+
};
|
|
227
|
+
}, [rowsByName, rowsByLooseName, rowForModel]);
|
|
228
|
+
}
|
|
229
|
+
const clean$1 = (value) => (value === null || value === void 0 ? void 0 : value.trim()) || undefined;
|
|
230
|
+
/**
|
|
231
|
+
* The label to show for a model.
|
|
232
|
+
*
|
|
233
|
+
* Settings persist only `llm_name` — a wire key like `iblai-pro` or
|
|
234
|
+
* `claude-haiku-4-5-20251001` — while the model picker reads the catalogue,
|
|
235
|
+
* which carries a `display_name` ("ibl.ai Pro", "Claude Haiku 4.5"). Resolve
|
|
236
|
+
* the label in three steps:
|
|
237
|
+
*
|
|
238
|
+
* 1. `llm_config.display_name` from settings, when the caller has it.
|
|
239
|
+
* 2. The mentor-llms catalogue, matched on `llm_name`. Only queried when step
|
|
240
|
+
* 1 came back empty.
|
|
241
|
+
* 3. `getLLMModelDisplayName`, which tidies the handful of keys whose raw
|
|
242
|
+
* form is unpresentable — used while the catalogue is loading or failed.
|
|
243
|
+
*/
|
|
244
|
+
function useLlmDisplayName({ llmName, llmConfig, org, userId, mentorId, }) {
|
|
245
|
+
var _a;
|
|
246
|
+
const fromConfig = clean$1(llmConfig === null || llmConfig === void 0 ? void 0 : llmConfig.display_name);
|
|
247
|
+
const skip = Boolean(fromConfig) || !llmName || !org || !userId || !mentorId;
|
|
248
|
+
const { data: providers } = useGetLlmsQuery({
|
|
249
|
+
org: org !== null && org !== void 0 ? org : '',
|
|
250
|
+
// @ts-expect-error - userId is not in the generated query args but the endpoint scopes by it
|
|
251
|
+
userId: userId !== null && userId !== void 0 ? userId : '',
|
|
252
|
+
mentorId: mentorId !== null && mentorId !== void 0 ? mentorId : '',
|
|
253
|
+
}, { skip });
|
|
254
|
+
const fromCatalogue = useMemo(() => {
|
|
255
|
+
var _a;
|
|
256
|
+
if (skip || !llmName || !Array.isArray(providers))
|
|
257
|
+
return undefined;
|
|
258
|
+
const wanted = modelKey(llmName);
|
|
259
|
+
for (const provider of providers) {
|
|
260
|
+
const match = (_a = provider === null || provider === void 0 ? void 0 : provider.chat_models) === null || _a === void 0 ? void 0 : _a.find((model) => modelKey(model === null || model === void 0 ? void 0 : model.llm_name) === wanted || modelKey(model === null || model === void 0 ? void 0 : model.display_name) === wanted);
|
|
261
|
+
const label = clean$1(match === null || match === void 0 ? void 0 : match.display_name);
|
|
262
|
+
if (label)
|
|
263
|
+
return label;
|
|
264
|
+
}
|
|
265
|
+
return undefined;
|
|
266
|
+
}, [skip, providers, llmName]);
|
|
267
|
+
return (_a = fromConfig !== null && fromConfig !== void 0 ? fromConfig : fromCatalogue) !== null && _a !== void 0 ? _a : getLLMModelDisplayName(llmName);
|
|
268
|
+
}
|
|
269
|
+
|
|
58
270
|
var _a;
|
|
59
271
|
const dl$1 = dataLayer;
|
|
60
272
|
/**
|
|
@@ -2264,7 +2476,7 @@ var analyticsAnalyticsTranscriptsStats$3 = {
|
|
|
2264
2476
|
labelUsername: "Username:",
|
|
2265
2477
|
labelAgent: "Agent:",
|
|
2266
2478
|
labelModel: "Model:",
|
|
2267
|
-
labelModelCard: "
|
|
2479
|
+
labelModelCard: "Model:",
|
|
2268
2480
|
labelUser: "User:",
|
|
2269
2481
|
roleUser: "User",
|
|
2270
2482
|
roleAgent: "Agent",
|
|
@@ -2306,6 +2518,37 @@ var analyticsAnalyticsTranscriptsStats$3 = {
|
|
|
2306
2518
|
avgCostPerConversationDescription: "What a typical conversation costs in model usage.",
|
|
2307
2519
|
avgRatingDescription: "Average rating users gave their conversations, on a scale of 1 to 5."
|
|
2308
2520
|
};
|
|
2521
|
+
var analyticsTranscriptTurnDetails$3 = {
|
|
2522
|
+
showDetails: "Show Details",
|
|
2523
|
+
hideDetails: "Hide Details",
|
|
2524
|
+
metadata: "Metadata",
|
|
2525
|
+
requestContext: "Request Context",
|
|
2526
|
+
model: "Model",
|
|
2527
|
+
provider: "Provider",
|
|
2528
|
+
temperature: "Temperature",
|
|
2529
|
+
client: "Client",
|
|
2530
|
+
sourcesBadge: "Documents · {count}",
|
|
2531
|
+
toolsBadge: "Tools · {count}",
|
|
2532
|
+
yes: "Yes",
|
|
2533
|
+
no: "No",
|
|
2534
|
+
redacted: "Redacted",
|
|
2535
|
+
fieldSession: "Session",
|
|
2536
|
+
fieldCallerVerified: "Caller Verified",
|
|
2537
|
+
fieldFiles: "Files",
|
|
2538
|
+
fieldFile: "File",
|
|
2539
|
+
fieldSystemPrompt: "System Prompt",
|
|
2540
|
+
fieldFlow: "Flow",
|
|
2541
|
+
fieldToken: "Token",
|
|
2542
|
+
fieldTenant: "Tenant",
|
|
2543
|
+
fieldPathway: "Pathway",
|
|
2544
|
+
fieldUsername: "Username",
|
|
2545
|
+
fieldName: "Name",
|
|
2546
|
+
fieldCanvas: "Canvas",
|
|
2547
|
+
fieldProactivePrompt: "Proactive Prompt",
|
|
2548
|
+
fieldGrader: "Grader",
|
|
2549
|
+
fieldDatasets: "Datasets",
|
|
2550
|
+
fieldDateTime: "Date & Time"
|
|
2551
|
+
};
|
|
2309
2552
|
var analyticsAnalyticsUsersStats$3 = {
|
|
2310
2553
|
usersLoggedInNow: "Users logged in right now",
|
|
2311
2554
|
usersLoggedInPast30Days: "Users logged in past 30 days",
|
|
@@ -3796,7 +4039,8 @@ var historyTabLabels$3 = {
|
|
|
3796
4039
|
noResponse: "No response available",
|
|
3797
4040
|
selectPrompt: "Select a conversation to view details.",
|
|
3798
4041
|
aiAgent: "AI Agent",
|
|
3799
|
-
noConversations: "No conversations found"
|
|
4042
|
+
noConversations: "No conversations found",
|
|
4043
|
+
documentsChip: "Documents · {count}"
|
|
3800
4044
|
},
|
|
3801
4045
|
summary: {
|
|
3802
4046
|
notAvailable: "Summary not available"
|
|
@@ -8199,6 +8443,7 @@ var en = {
|
|
|
8199
8443
|
analyticsAnalyticsReports: analyticsAnalyticsReports$3,
|
|
8200
8444
|
analyticsAnalyticsTopicsStats: analyticsAnalyticsTopicsStats$3,
|
|
8201
8445
|
analyticsAnalyticsTranscriptsStats: analyticsAnalyticsTranscriptsStats$3,
|
|
8446
|
+
analyticsTranscriptTurnDetails: analyticsTranscriptTurnDetails$3,
|
|
8202
8447
|
analyticsAnalyticsUsersStats: analyticsAnalyticsUsersStats$3,
|
|
8203
8448
|
analyticsGroupsFilterDropdown: analyticsGroupsFilterDropdown$3,
|
|
8204
8449
|
analyticsStatCard: analyticsStatCard$3,
|
|
@@ -9422,7 +9667,7 @@ var analyticsAnalyticsTranscriptsStats$2 = {
|
|
|
9422
9667
|
labelUsername: "Nom d'utilisateur :",
|
|
9423
9668
|
labelAgent: "Agent :",
|
|
9424
9669
|
labelModel: "Modèle :",
|
|
9425
|
-
labelModelCard: "
|
|
9670
|
+
labelModelCard: "Modèle :",
|
|
9426
9671
|
labelUser: "Utilisateur :",
|
|
9427
9672
|
roleUser: "Utilisateur",
|
|
9428
9673
|
roleAgent: "Agent",
|
|
@@ -9464,6 +9709,37 @@ var analyticsAnalyticsTranscriptsStats$2 = {
|
|
|
9464
9709
|
avgCostPerConversationDescription: "Coût d’utilisation des modèles pour une conversation type.",
|
|
9465
9710
|
avgRatingDescription: "Note moyenne attribuée par les utilisateurs à leurs conversations, sur une échelle de 1 à 5."
|
|
9466
9711
|
};
|
|
9712
|
+
var analyticsTranscriptTurnDetails$2 = {
|
|
9713
|
+
showDetails: "Afficher les détails",
|
|
9714
|
+
hideDetails: "Masquer les détails",
|
|
9715
|
+
metadata: "Métadonnées",
|
|
9716
|
+
requestContext: "Contexte de la requête",
|
|
9717
|
+
model: "Modèle",
|
|
9718
|
+
provider: "Fournisseur",
|
|
9719
|
+
temperature: "Température",
|
|
9720
|
+
client: "Client",
|
|
9721
|
+
sourcesBadge: "Documents · {count}",
|
|
9722
|
+
toolsBadge: "Outils · {count}",
|
|
9723
|
+
yes: "Oui",
|
|
9724
|
+
no: "Non",
|
|
9725
|
+
redacted: "Masqué",
|
|
9726
|
+
fieldSession: "Session",
|
|
9727
|
+
fieldCallerVerified: "Appelant vérifié",
|
|
9728
|
+
fieldFiles: "Fichiers",
|
|
9729
|
+
fieldFile: "Fichier",
|
|
9730
|
+
fieldSystemPrompt: "Prompt système",
|
|
9731
|
+
fieldFlow: "Flux",
|
|
9732
|
+
fieldToken: "Jeton",
|
|
9733
|
+
fieldTenant: "Locataire",
|
|
9734
|
+
fieldPathway: "Parcours",
|
|
9735
|
+
fieldUsername: "Nom d’utilisateur",
|
|
9736
|
+
fieldName: "Nom",
|
|
9737
|
+
fieldCanvas: "Canvas",
|
|
9738
|
+
fieldProactivePrompt: "Prompt proactif",
|
|
9739
|
+
fieldGrader: "Correcteur",
|
|
9740
|
+
fieldDatasets: "Jeux de données",
|
|
9741
|
+
fieldDateTime: "Date et heure"
|
|
9742
|
+
};
|
|
9467
9743
|
var analyticsAnalyticsUsersStats$2 = {
|
|
9468
9744
|
usersLoggedInNow: "Utilisateurs connectés en ce moment",
|
|
9469
9745
|
usersLoggedInPast30Days: "Utilisateurs connectés ces 30 derniers jours",
|
|
@@ -11120,7 +11396,8 @@ var historyTabLabels$2 = {
|
|
|
11120
11396
|
noResponse: "Aucune réponse disponible",
|
|
11121
11397
|
selectPrompt: "Sélectionnez une conversation pour afficher les détails.",
|
|
11122
11398
|
aiAgent: "AI Agent",
|
|
11123
|
-
noConversations: "Aucune conversation trouvée"
|
|
11399
|
+
noConversations: "Aucune conversation trouvée",
|
|
11400
|
+
documentsChip: "Documents · {count}"
|
|
11124
11401
|
},
|
|
11125
11402
|
summary: {
|
|
11126
11403
|
notAvailable: "Résumé non disponible"
|
|
@@ -15357,6 +15634,7 @@ var fr = {
|
|
|
15357
15634
|
analyticsAnalyticsReports: analyticsAnalyticsReports$2,
|
|
15358
15635
|
analyticsAnalyticsTopicsStats: analyticsAnalyticsTopicsStats$2,
|
|
15359
15636
|
analyticsAnalyticsTranscriptsStats: analyticsAnalyticsTranscriptsStats$2,
|
|
15637
|
+
analyticsTranscriptTurnDetails: analyticsTranscriptTurnDetails$2,
|
|
15360
15638
|
analyticsAnalyticsUsersStats: analyticsAnalyticsUsersStats$2,
|
|
15361
15639
|
analyticsGroupsFilterDropdown: analyticsGroupsFilterDropdown$2,
|
|
15362
15640
|
analyticsStatCard: analyticsStatCard$2,
|
|
@@ -16580,7 +16858,7 @@ var analyticsAnalyticsTranscriptsStats$1 = {
|
|
|
16580
16858
|
labelUsername: "Nombre de usuario:",
|
|
16581
16859
|
labelAgent: "Agente:",
|
|
16582
16860
|
labelModel: "Modelo:",
|
|
16583
|
-
labelModelCard: "
|
|
16861
|
+
labelModelCard: "Modelo:",
|
|
16584
16862
|
labelUser: "Usuario:",
|
|
16585
16863
|
roleUser: "Usuario",
|
|
16586
16864
|
roleAgent: "Agente",
|
|
@@ -16622,6 +16900,37 @@ var analyticsAnalyticsTranscriptsStats$1 = {
|
|
|
16622
16900
|
avgCostPerConversationDescription: "Lo que cuesta una conversación típica en uso de modelos.",
|
|
16623
16901
|
avgRatingDescription: "Valoración media que los usuarios dieron a sus conversaciones, en una escala de 1 a 5."
|
|
16624
16902
|
};
|
|
16903
|
+
var analyticsTranscriptTurnDetails$1 = {
|
|
16904
|
+
showDetails: "Mostrar detalles",
|
|
16905
|
+
hideDetails: "Ocultar detalles",
|
|
16906
|
+
metadata: "Metadatos",
|
|
16907
|
+
requestContext: "Contexto de la solicitud",
|
|
16908
|
+
model: "Modelo",
|
|
16909
|
+
provider: "Proveedor",
|
|
16910
|
+
temperature: "Temperatura",
|
|
16911
|
+
client: "Cliente",
|
|
16912
|
+
sourcesBadge: "Documentos · {count}",
|
|
16913
|
+
toolsBadge: "Herramientas · {count}",
|
|
16914
|
+
yes: "Sí",
|
|
16915
|
+
no: "No",
|
|
16916
|
+
redacted: "Oculto",
|
|
16917
|
+
fieldSession: "Sesión",
|
|
16918
|
+
fieldCallerVerified: "Llamante verificado",
|
|
16919
|
+
fieldFiles: "Archivos",
|
|
16920
|
+
fieldFile: "Archivo",
|
|
16921
|
+
fieldSystemPrompt: "Prompt del sistema",
|
|
16922
|
+
fieldFlow: "Flujo",
|
|
16923
|
+
fieldToken: "Token",
|
|
16924
|
+
fieldTenant: "Inquilino",
|
|
16925
|
+
fieldPathway: "Ruta",
|
|
16926
|
+
fieldUsername: "Nombre de usuario",
|
|
16927
|
+
fieldName: "Nombre",
|
|
16928
|
+
fieldCanvas: "Canvas",
|
|
16929
|
+
fieldProactivePrompt: "Prompt proactivo",
|
|
16930
|
+
fieldGrader: "Calificador",
|
|
16931
|
+
fieldDatasets: "Conjuntos de datos",
|
|
16932
|
+
fieldDateTime: "Fecha y hora"
|
|
16933
|
+
};
|
|
16625
16934
|
var analyticsAnalyticsUsersStats$1 = {
|
|
16626
16935
|
usersLoggedInNow: "Usuarios conectados ahora mismo",
|
|
16627
16936
|
usersLoggedInPast30Days: "Usuarios conectados en los últimos 30 días",
|
|
@@ -18278,7 +18587,8 @@ var historyTabLabels$1 = {
|
|
|
18278
18587
|
noResponse: "No hay respuesta disponible",
|
|
18279
18588
|
selectPrompt: "Selecciona una conversación para ver los detalles.",
|
|
18280
18589
|
aiAgent: "AI Agent",
|
|
18281
|
-
noConversations: "No se encontraron conversaciones"
|
|
18590
|
+
noConversations: "No se encontraron conversaciones",
|
|
18591
|
+
documentsChip: "Documentos · {count}"
|
|
18282
18592
|
},
|
|
18283
18593
|
summary: {
|
|
18284
18594
|
notAvailable: "Resumen no disponible"
|
|
@@ -22515,6 +22825,7 @@ var es = {
|
|
|
22515
22825
|
analyticsAnalyticsReports: analyticsAnalyticsReports$1,
|
|
22516
22826
|
analyticsAnalyticsTopicsStats: analyticsAnalyticsTopicsStats$1,
|
|
22517
22827
|
analyticsAnalyticsTranscriptsStats: analyticsAnalyticsTranscriptsStats$1,
|
|
22828
|
+
analyticsTranscriptTurnDetails: analyticsTranscriptTurnDetails$1,
|
|
22518
22829
|
analyticsAnalyticsUsersStats: analyticsAnalyticsUsersStats$1,
|
|
22519
22830
|
analyticsGroupsFilterDropdown: analyticsGroupsFilterDropdown$1,
|
|
22520
22831
|
analyticsStatCard: analyticsStatCard$1,
|
|
@@ -23780,6 +24091,37 @@ var analyticsAnalyticsTranscriptsStats = {
|
|
|
23780
24091
|
avgCostPerConversationDescription: "一次典型对话所产生的模型使用成本。",
|
|
23781
24092
|
avgRatingDescription: "用户对其对话给出的平均评分,满分 5 分。"
|
|
23782
24093
|
};
|
|
24094
|
+
var analyticsTranscriptTurnDetails = {
|
|
24095
|
+
showDetails: "显示详情",
|
|
24096
|
+
hideDetails: "隐藏详情",
|
|
24097
|
+
metadata: "元数据",
|
|
24098
|
+
requestContext: "请求上下文",
|
|
24099
|
+
model: "模型",
|
|
24100
|
+
provider: "提供商",
|
|
24101
|
+
temperature: "温度",
|
|
24102
|
+
client: "客户端",
|
|
24103
|
+
sourcesBadge: "文档 · {count}",
|
|
24104
|
+
toolsBadge: "工具 · {count}",
|
|
24105
|
+
yes: "是",
|
|
24106
|
+
no: "否",
|
|
24107
|
+
redacted: "已隐藏",
|
|
24108
|
+
fieldSession: "会话",
|
|
24109
|
+
fieldCallerVerified: "调用者已验证",
|
|
24110
|
+
fieldFiles: "文件",
|
|
24111
|
+
fieldFile: "文件",
|
|
24112
|
+
fieldSystemPrompt: "系统提示",
|
|
24113
|
+
fieldFlow: "流程",
|
|
24114
|
+
fieldToken: "令牌",
|
|
24115
|
+
fieldTenant: "租户",
|
|
24116
|
+
fieldPathway: "路径",
|
|
24117
|
+
fieldUsername: "用户名",
|
|
24118
|
+
fieldName: "名称",
|
|
24119
|
+
fieldCanvas: "画布",
|
|
24120
|
+
fieldProactivePrompt: "主动提示",
|
|
24121
|
+
fieldGrader: "评分器",
|
|
24122
|
+
fieldDatasets: "数据集",
|
|
24123
|
+
fieldDateTime: "日期和时间"
|
|
24124
|
+
};
|
|
23783
24125
|
var analyticsAnalyticsUsersStats = {
|
|
23784
24126
|
usersLoggedInNow: "当前在线用户",
|
|
23785
24127
|
usersLoggedInPast30Days: "过去 30 天登录用户",
|
|
@@ -25436,7 +25778,8 @@ var historyTabLabels = {
|
|
|
25436
25778
|
noResponse: "暂无回复",
|
|
25437
25779
|
selectPrompt: "选择一条对话以查看详情。",
|
|
25438
25780
|
aiAgent: "AI Agent",
|
|
25439
|
-
noConversations: "未找到对话"
|
|
25781
|
+
noConversations: "未找到对话",
|
|
25782
|
+
documentsChip: "文档 · {count}"
|
|
25440
25783
|
},
|
|
25441
25784
|
summary: {
|
|
25442
25785
|
notAvailable: "摘要不可用"
|
|
@@ -29673,6 +30016,7 @@ var zh = {
|
|
|
29673
30016
|
analyticsAnalyticsReports: analyticsAnalyticsReports,
|
|
29674
30017
|
analyticsAnalyticsTopicsStats: analyticsAnalyticsTopicsStats,
|
|
29675
30018
|
analyticsAnalyticsTranscriptsStats: analyticsAnalyticsTranscriptsStats,
|
|
30019
|
+
analyticsTranscriptTurnDetails: analyticsTranscriptTurnDetails,
|
|
29676
30020
|
analyticsAnalyticsUsersStats: analyticsAnalyticsUsersStats,
|
|
29677
30021
|
analyticsGroupsFilterDropdown: analyticsGroupsFilterDropdown,
|
|
29678
30022
|
analyticsStatCard: analyticsStatCard,
|
|
@@ -74459,7 +74803,7 @@ var isArray$f = function isArray(arr) {
|
|
|
74459
74803
|
return toStr.call(arr) === '[object Array]';
|
|
74460
74804
|
};
|
|
74461
74805
|
|
|
74462
|
-
var isPlainObject$
|
|
74806
|
+
var isPlainObject$6 = function isPlainObject(obj) {
|
|
74463
74807
|
if (!obj || toStr.call(obj) !== '[object Object]') {
|
|
74464
74808
|
return false;
|
|
74465
74809
|
}
|
|
@@ -74538,12 +74882,12 @@ var extend$3 = function extend() {
|
|
|
74538
74882
|
// Prevent never-ending loop
|
|
74539
74883
|
if (target !== copy) {
|
|
74540
74884
|
// Recurse if we're merging plain objects or arrays
|
|
74541
|
-
if (deep && copy && (isPlainObject$
|
|
74885
|
+
if (deep && copy && (isPlainObject$6(copy) || (copyIsArray = isArray$f(copy)))) {
|
|
74542
74886
|
if (copyIsArray) {
|
|
74543
74887
|
copyIsArray = false;
|
|
74544
74888
|
clone = src && isArray$f(src) ? src : [];
|
|
74545
74889
|
} else {
|
|
74546
|
-
clone = src && isPlainObject$
|
|
74890
|
+
clone = src && isPlainObject$6(src) ? src : {};
|
|
74547
74891
|
}
|
|
74548
74892
|
|
|
74549
74893
|
// Never move original objects, clone them
|
|
@@ -74564,7 +74908,7 @@ var extend$3 = function extend() {
|
|
|
74564
74908
|
|
|
74565
74909
|
var extend$2 = /*@__PURE__*/getDefaultExportFromCjs(extend$3);
|
|
74566
74910
|
|
|
74567
|
-
function isPlainObject$
|
|
74911
|
+
function isPlainObject$5(value) {
|
|
74568
74912
|
if (typeof value !== 'object' || value === null) {
|
|
74569
74913
|
return false;
|
|
74570
74914
|
}
|
|
@@ -75635,7 +75979,7 @@ class Processor extends CallableInstance {
|
|
|
75635
75979
|
else if (parameters.length > 0) {
|
|
75636
75980
|
let [primary, ...rest] = parameters;
|
|
75637
75981
|
const currentPrimary = attachers[entryIndex][1];
|
|
75638
|
-
if (isPlainObject$
|
|
75982
|
+
if (isPlainObject$5(currentPrimary) && isPlainObject$5(primary)) {
|
|
75639
75983
|
primary = extend$2(true, currentPrimary, primary);
|
|
75640
75984
|
}
|
|
75641
75985
|
|
|
@@ -75727,7 +76071,7 @@ function assertUnfrozen(name, frozen) {
|
|
|
75727
76071
|
function assertNode(node) {
|
|
75728
76072
|
// `isPlainObj` unfortunately uses `any` instead of `unknown`.
|
|
75729
76073
|
// type-coverage:ignore-next-line
|
|
75730
|
-
if (!isPlainObject$
|
|
76074
|
+
if (!isPlainObject$5(node) || typeof node.type !== 'string') {
|
|
75731
76075
|
throw new TypeError('Expected node, got `' + node + '`')
|
|
75732
76076
|
// Fine.
|
|
75733
76077
|
}
|
|
@@ -136692,7 +137036,7 @@ var objectCtorString = funcToString.call(Object);
|
|
|
136692
137036
|
* _.isPlainObject(Object.create(null));
|
|
136693
137037
|
* // => true
|
|
136694
137038
|
*/
|
|
136695
|
-
function isPlainObject$
|
|
137039
|
+
function isPlainObject$4(value) {
|
|
136696
137040
|
if (!isObjectLike$1(value) || baseGetTag$1(value) != objectTag) {
|
|
136697
137041
|
return false;
|
|
136698
137042
|
}
|
|
@@ -136705,9 +137049,9 @@ function isPlainObject$3(value) {
|
|
|
136705
137049
|
funcToString.call(Ctor) == objectCtorString;
|
|
136706
137050
|
}
|
|
136707
137051
|
|
|
136708
|
-
var isPlainObject_1 = isPlainObject$
|
|
137052
|
+
var isPlainObject_1 = isPlainObject$4;
|
|
136709
137053
|
|
|
136710
|
-
var isPlainObject$
|
|
137054
|
+
var isPlainObject$3 = /*@__PURE__*/getDefaultExportFromCjs(isPlainObject_1);
|
|
136711
137055
|
|
|
136712
137056
|
var baseGetTag = _baseGetTag,
|
|
136713
137057
|
isObjectLike = isObjectLike_1;
|
|
@@ -136924,7 +137268,7 @@ function Shape(_ref2) {
|
|
|
136924
137268
|
shape = /*#__PURE__*/cloneElement(option, _objectSpread$i(_objectSpread$i({}, props), getPropsFromShapeOption(option)));
|
|
136925
137269
|
} else if (isFunction$3(option)) {
|
|
136926
137270
|
shape = option(props);
|
|
136927
|
-
} else if (isPlainObject$
|
|
137271
|
+
} else if (isPlainObject$3(option) && !isBoolean(option)) {
|
|
136928
137272
|
var nextProps = propTransformer(option, props);
|
|
136929
137273
|
shape = /*#__PURE__*/React__default.createElement(ShapeSelector, {
|
|
136930
137274
|
shapeType: shapeType,
|
|
@@ -185485,6 +185829,100 @@ function Markdown({ children, className }) {
|
|
|
185485
185829
|
return (jsx("div", { className: className, children: jsx(Markdown$1, { components: components, children: children }) }));
|
|
185486
185830
|
}
|
|
185487
185831
|
|
|
185832
|
+
function FileCard({ fileName, fileType }) {
|
|
185833
|
+
const getFileIcon = (fileName, fileType) => {
|
|
185834
|
+
const type = fileType.toLowerCase();
|
|
185835
|
+
const name = fileName.toLowerCase();
|
|
185836
|
+
const extension = name.split('.').pop() || '';
|
|
185837
|
+
// Check by MIME type first
|
|
185838
|
+
if (type.includes('pdf')) {
|
|
185839
|
+
return jsx(File$1, { className: "h-5 w-5 text-blue-500" });
|
|
185840
|
+
}
|
|
185841
|
+
else if (type.includes('image')) {
|
|
185842
|
+
return jsx(FileImage, { className: "h-5 w-5 text-blue-500" });
|
|
185843
|
+
}
|
|
185844
|
+
else if (type.includes('audio')) {
|
|
185845
|
+
return jsx(FileAudio, { className: "h-5 w-5 text-blue-500" });
|
|
185846
|
+
}
|
|
185847
|
+
else if (type.includes('video')) {
|
|
185848
|
+
return jsx(FilePlay, { className: "h-5 w-5 text-blue-500" });
|
|
185849
|
+
}
|
|
185850
|
+
else if (type.includes('spreadsheet') || type.includes('excel') || type.includes('csv')) {
|
|
185851
|
+
return jsx(FileSpreadsheet, { className: "h-5 w-5 text-blue-500" });
|
|
185852
|
+
}
|
|
185853
|
+
else if (type.includes('zip') || type.includes('compressed') || type.includes('archive')) {
|
|
185854
|
+
return jsx(FileArchive, { className: "h-5 w-5 text-blue-500" });
|
|
185855
|
+
}
|
|
185856
|
+
else if (type.includes('javascript') ||
|
|
185857
|
+
type.includes('typescript') ||
|
|
185858
|
+
type.includes('html') ||
|
|
185859
|
+
type.includes('css') ||
|
|
185860
|
+
type.includes('json')) {
|
|
185861
|
+
return jsx(FileCode, { className: "h-5 w-5 text-blue-500" });
|
|
185862
|
+
}
|
|
185863
|
+
// If MIME type doesn't match, check by extension
|
|
185864
|
+
if (['doc', 'docx', 'txt', 'rtf'].includes(extension)) {
|
|
185865
|
+
return jsx(FileText, { className: "h-5 w-5 text-blue-500" });
|
|
185866
|
+
}
|
|
185867
|
+
else if (['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp'].includes(extension)) {
|
|
185868
|
+
return jsx(FileImage, { className: "h-5 w-5 text-blue-500" });
|
|
185869
|
+
}
|
|
185870
|
+
else if (['pdf'].includes(extension)) {
|
|
185871
|
+
return jsx(File$1, { className: "h-5 w-5 text-blue-500" });
|
|
185872
|
+
}
|
|
185873
|
+
else if (['mp3', 'wav', 'ogg', 'flac'].includes(extension)) {
|
|
185874
|
+
return jsx(FileAudio, { className: "h-5 w-5 text-blue-500" });
|
|
185875
|
+
}
|
|
185876
|
+
else if (['mp4', 'webm', 'avi', 'mov'].includes(extension)) {
|
|
185877
|
+
return jsx(FilePlay, { className: "h-5 w-5 text-blue-500" });
|
|
185878
|
+
}
|
|
185879
|
+
else if (['xls', 'xlsx', 'csv'].includes(extension)) {
|
|
185880
|
+
return jsx(FileSpreadsheet, { className: "h-5 w-5 text-blue-500" });
|
|
185881
|
+
}
|
|
185882
|
+
else if (['zip', 'rar', '7z', 'tar', 'gz'].includes(extension)) {
|
|
185883
|
+
return jsx(FileArchive, { className: "h-5 w-5 text-blue-500" });
|
|
185884
|
+
}
|
|
185885
|
+
else if (['js', 'ts', 'jsx', 'tsx', 'html', 'css', 'json', 'py', 'java', 'c', 'cpp'].includes(extension)) {
|
|
185886
|
+
return jsx(FileCode, { className: "h-5 w-5 text-blue-500" });
|
|
185887
|
+
}
|
|
185888
|
+
// Default icon
|
|
185889
|
+
return jsx(File$1, { className: "h-5 w-5 text-blue-500" });
|
|
185890
|
+
};
|
|
185891
|
+
return (jsxs("div", { className: "mb-2 flex max-w-xs items-center rounded-lg border border-gray-200 bg-white p-3", children: [jsx("div", { className: "mr-3 shrink-0 rounded-lg bg-blue-100 p-2 text-blue-600", children: getFileIcon(fileName, fileType) }), jsxs("div", { className: "min-w-0 flex-1", children: [jsx("h3", { className: "truncate text-sm font-medium text-gray-900", children: fileName }), jsx("p", { className: "truncate text-xs text-gray-500", children: fileType })] })] }));
|
|
185892
|
+
}
|
|
185893
|
+
|
|
185894
|
+
function ImageMessage({ url, fileName, setPreviewImage }) {
|
|
185895
|
+
const [hasError, setHasError] = useState(false);
|
|
185896
|
+
if (hasError || !url) {
|
|
185897
|
+
return jsx(FileCard, { fileName: fileName, fileType: "image/*" });
|
|
185898
|
+
}
|
|
185899
|
+
return (jsx("div", { className: "h-full max-h-64 w-full max-w-96 overflow-hidden rounded-lg", children: jsx("div", { className: "relative", children: jsx("img", { src: url, alt: fileName, className: "h-auto w-full cursor-pointer object-contain p-2", onClick: () => setPreviewImage(url), onError: () => setHasError(true) }) }) }));
|
|
185900
|
+
}
|
|
185901
|
+
|
|
185902
|
+
const openInNewTab = (url) => {
|
|
185903
|
+
window.open(url, '_blank', 'noopener,noreferrer');
|
|
185904
|
+
};
|
|
185905
|
+
/**
|
|
185906
|
+
* Files on an admin transcript, in the chat's own attachment idiom: images
|
|
185907
|
+
* preview like a sent image, everything else is the chat's file card. A card
|
|
185908
|
+
* with a URL opens the file in a new tab (presigned links expire, so nothing
|
|
185909
|
+
* is cached here).
|
|
185910
|
+
*/
|
|
185911
|
+
function TranscriptFileCards({ files, className, }) {
|
|
185912
|
+
const shown = files.filter((file) => file === null || file === void 0 ? void 0 : file.name);
|
|
185913
|
+
if (shown.length === 0)
|
|
185914
|
+
return null;
|
|
185915
|
+
return (jsx("div", { className: className !== null && className !== void 0 ? className : 'mt-2 flex flex-wrap items-start gap-2', "data-testid": "transcript-file-cards", children: shown.map((file, index) => {
|
|
185916
|
+
var _a;
|
|
185917
|
+
const contentType = (_a = file.contentType) !== null && _a !== void 0 ? _a : '';
|
|
185918
|
+
if (file.url && contentType.startsWith('image/')) {
|
|
185919
|
+
return (jsx(ImageMessage, { url: file.url, fileName: file.name, setPreviewImage: openInNewTab }, `${file.name}-${index}`));
|
|
185920
|
+
}
|
|
185921
|
+
const card = jsx(FileCard, { fileName: file.name, fileType: contentType || 'file' });
|
|
185922
|
+
return file.url ? (jsx("a", { href: file.url, target: "_blank", rel: "noopener noreferrer", className: "block hover:opacity-90", "aria-label": `Open ${file.name}`, onClick: (event) => event.stopPropagation(), children: card }, `${file.name}-${index}`)) : (jsx("div", { children: card }, `${file.name}-${index}`));
|
|
185923
|
+
}) }));
|
|
185924
|
+
}
|
|
185925
|
+
|
|
185488
185926
|
/**
|
|
185489
185927
|
* Whether the dropdown is open, closing on a pointer press outside `ref` or on
|
|
185490
185928
|
* Escape.
|
|
@@ -186090,8 +186528,12 @@ function ConversationMessages({ messages, username, agent, fallbackEmail, }) {
|
|
|
186090
186528
|
? (userMetadata === null || userMetadata === void 0 ? void 0 : userMetadata.email) || fallbackEmail || username
|
|
186091
186529
|
: t('chatHistoryChatHistoryTab.you');
|
|
186092
186530
|
return (jsx("div", { className: "space-y-6", children: messages.map((message, index) => {
|
|
186093
|
-
var _a, _b;
|
|
186094
|
-
return (jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "flex items-start gap-3", children: [jsx(UserMessageAvatar, { username: username }), jsxs("div", { className: "min-w-0 flex-1 overflow-x-hidden", children: [jsx("div", { className: "font-medium break-all text-gray-700", children: humanLabel }), jsx(Markdown, { className: "mt-1 text-sm text-gray-500", children: (_a = message.human) !== null && _a !== void 0 ? _a : '' })
|
|
186531
|
+
var _a, _b, _c;
|
|
186532
|
+
return (jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "flex items-start gap-3", children: [jsx(UserMessageAvatar, { username: username }), jsxs("div", { className: "min-w-0 flex-1 overflow-x-hidden", children: [jsx("div", { className: "font-medium break-all text-gray-700", children: humanLabel }), jsx(Markdown, { className: "mt-1 text-sm text-gray-500", children: (_a = message.human) !== null && _a !== void 0 ? _a : '' }), jsx(TranscriptFileCards, { files: ((_b = message.human_files) !== null && _b !== void 0 ? _b : []).map((file) => ({
|
|
186533
|
+
name: file.name,
|
|
186534
|
+
contentType: file.content_type,
|
|
186535
|
+
url: file.url,
|
|
186536
|
+
})) })] })] }), jsxs("div", { className: "flex items-start gap-3 border-t border-gray-200 pt-4", children: [jsx(AgentMessageAvatar, { agent: agent, fallback: t('chatHistoryChatHistoryTab.aiAvatarLabel') }), jsxs("div", { className: "min-w-0 flex-1 overflow-x-hidden", children: [jsx("div", { className: "font-medium text-gray-700", children: agent.name }), jsx(Markdown, { className: "mt-1 text-sm text-gray-500", children: (_c = message.ai) !== null && _c !== void 0 ? _c : '' })] })] })] }, index));
|
|
186095
186537
|
}) }));
|
|
186096
186538
|
}
|
|
186097
186539
|
/**
|
|
@@ -187911,6 +188353,412 @@ function InvitedUsersDialog({ tenant, onClose }) {
|
|
|
187911
188353
|
}, children: jsx(DialogPortal, { forceMount: true, children: jsxs(DialogContent, { "aria-label": t('profileInvitedUsers.dialogAriaLabel'), className: "max-w-sm rounded-2xl px-6 py-8 pointer-events-auto", "aria-describedby": "invited-users-dialog", children: [jsx(DialogHeader, { className: "relative flex-row justify-between", children: jsx(DialogTitle, { className: "text-blue-600 text-xl font-semibold", children: t('profileInvitedUsers.title') }) }), jsxs("div", { className: "mt-4 space-y-1", children: [jsx("p", { className: "text-gray-500 text-sm", children: t('profileInvitedUsers.pendingDescription') }), jsx("form", { children: jsx(Input, { value: query, onChange: (event) => setQuery(event.target.value), placeholder: t('profileInvitedUsers.searchPlaceholder'), className: "mt-2" }) })] }), jsxs("div", { children: [jsx("h2", { className: "text-md text-gray-600 font-semibold mb-4", children: t('profileInvitedUsers.emailHeading') }), invitedUsers === null || invitedUsers === void 0 ? void 0 : invitedUsers.results.map((user) => (jsx("div", { className: "border-b-gray-50 pb-2 mb-4 text-sm text-gray-600 dark:text-gray-400", children: user.email }, user.id))), (invitedUsers === null || invitedUsers === void 0 ? void 0 : invitedUsers.results.length) === 0 && (jsx("p", { className: "text-gray", children: t('profileInvitedUsers.noRecords') }))] })] }) }) }));
|
|
187912
188354
|
}
|
|
187913
188355
|
|
|
188356
|
+
function DocumentSidebar({ isModal = false, sessionId = '', documents, }) {
|
|
188357
|
+
const t = useT();
|
|
188358
|
+
const [isCollapsed, setIsCollapsed] = React.useState(false);
|
|
188359
|
+
const params = useParams();
|
|
188360
|
+
const username = useUsername();
|
|
188361
|
+
const isStreaming = useSelector(selectStreaming);
|
|
188362
|
+
const hasOwnDocuments = documents !== undefined;
|
|
188363
|
+
const { data: sessionDocuments, refetch, status, } = useGetVectorDocumentsQuery({
|
|
188364
|
+
org: params.tenantKey,
|
|
188365
|
+
sessionId: sessionId,
|
|
188366
|
+
// @ts-ignore
|
|
188367
|
+
userId: username,
|
|
188368
|
+
}, {
|
|
188369
|
+
skip: hasOwnDocuments || !params.tenantKey || !sessionId || !username || !isLoggedIn(),
|
|
188370
|
+
});
|
|
188371
|
+
const vectorDocuments = hasOwnDocuments
|
|
188372
|
+
? (documents !== null && documents !== void 0 ? documents : undefined)
|
|
188373
|
+
: sessionDocuments;
|
|
188374
|
+
React.useEffect(() => {
|
|
188375
|
+
if (!hasOwnDocuments && !isStreaming && isLoggedIn() && status !== 'uninitialized') {
|
|
188376
|
+
refetch();
|
|
188377
|
+
}
|
|
188378
|
+
}, [hasOwnDocuments, isStreaming, refetch]);
|
|
188379
|
+
const toggleCollapse = () => {
|
|
188380
|
+
setIsCollapsed(!isCollapsed);
|
|
188381
|
+
};
|
|
188382
|
+
return (jsx(Fragment$1, { children: (vectorDocuments === null || vectorDocuments === void 0 ? void 0 : vectorDocuments.length) && vectorDocuments.length > 0 ? (jsx("aside", { className: cn('transition-all duration-300 ease-in-out', isModal
|
|
188383
|
+
? 'h-full max-h-full w-full overflow-auto'
|
|
188384
|
+
: 'hidden rounded-tl-lg rounded-bl-lg md:hidden lg:block', !isModal && (isCollapsed ? 'w-[40px]' : 'w-[380px]')), style: {
|
|
188385
|
+
backgroundColor: isCollapsed && !isModal ? 'white' : '#F3F6FB',
|
|
188386
|
+
// In the dialog the parent bounds the height; the rail caps itself.
|
|
188387
|
+
maxHeight: isModal ? undefined : 'calc(100vh - 80px)',
|
|
188388
|
+
}, children: jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [!isModal && (jsxs("div", { className: cn('flex cursor-pointer items-center gap-2 border-b border-gray-200 p-4 transition-colors duration-200', isCollapsed && 'h-[80px] justify-center rounded-tl-[5px] rounded-bl-[5px] p-2', 'hover:bg-blue-100'), onClick: toggleCollapse, style: { backgroundColor: '#F3F6FB' }, children: [jsx(FileText, { className: "h-5 w-5 shrink-0 text-blue-600" }), !isCollapsed && (jsxs(Fragment$1, { children: [jsx("h2", { className: "text-base font-medium text-[#646464]", children: t('documentSidebar.retrievedDocuments') }), jsx(ChevronRight, { className: cn('ml-auto h-4 w-4 text-gray-400 transition-transform', isCollapsed ? 'rotate-180' : '') })] }))] })), (!isCollapsed || isModal) && (jsx(Fragment$1, { children: jsx("div", { className: "min-h-0 flex-1 overflow-auto", style: { backgroundColor: '#F3F6FB' }, children: jsx("div", { className: "mt-0 space-y-1 p-2", children: vectorDocuments.map((doc, index) => {
|
|
188389
|
+
var _a, _b;
|
|
188390
|
+
return (jsxs(React.Fragment, { children: [jsx("div", { className: "rounded-lg p-2 hover:bg-gray-50", children: jsxs("div", { className: "flex items-start gap-2", children: [jsx(Radio$1, { className: "mt-1 h-4 w-4 text-gray-400" }), jsxs("div", { className: "min-w-0 flex-1 space-y-1", children: [jsxs("div", { className: "flex items-center justify-between", children: [jsx(Link$2, { href: (_a = doc.source) !== null && _a !== void 0 ? _a : '', target: "_blank", className: "min-w-0", children: jsx("span", { className: "text-sm font-semibold break-words text-[#646464] hover:text-blue-600", children: doc.title }) }), jsx("div", { className: "flex items-center gap-2 self-center", children: jsx("span", { className: "text-xs text-gray-500", children: (_b = doc === null || doc === void 0 ? void 0 : doc.score) === null || _b === void 0 ? void 0 : _b.toFixed(2) }) })] }), jsx("p", { className: "line-clamp-6 pt-[10px] text-[14px] text-gray-600", children: doc.snippet })] })] }) }), index < vectorDocuments.length - 1 && (jsx("div", { className: "my-2 border-t border-gray-200" }))] }, index));
|
|
188391
|
+
}) }) }) }))] }) })) : null }));
|
|
188392
|
+
}
|
|
188393
|
+
|
|
188394
|
+
/**
|
|
188395
|
+
* The chat's "Retrieved Documents" control: an outline button opening the
|
|
188396
|
+
* documents dialog (`DocumentSidebar` in modal mode). Fed by the session's
|
|
188397
|
+
* vector results by default, or by `documents` the host already has — the
|
|
188398
|
+
* admin transcript surfaces pass a turn's or a conversation's documents, so
|
|
188399
|
+
* one component shows retrieved documents everywhere.
|
|
188400
|
+
*/
|
|
188401
|
+
function RetrievedDocumentsButton({ sessionId = '', documents, className, label, }) {
|
|
188402
|
+
const t = useT();
|
|
188403
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
188404
|
+
const params = useParams();
|
|
188405
|
+
const username = useUsername();
|
|
188406
|
+
const isStreaming = useSelector(selectStreaming);
|
|
188407
|
+
const hasOwnDocuments = documents !== undefined;
|
|
188408
|
+
const { data: sessionDocuments, refetch, status, } = useGetVectorDocumentsQuery({
|
|
188409
|
+
org: params.tenantKey,
|
|
188410
|
+
sessionId: sessionId,
|
|
188411
|
+
// @ts-ignore
|
|
188412
|
+
userId: username,
|
|
188413
|
+
}, {
|
|
188414
|
+
skip: hasOwnDocuments || !params.tenantKey || !sessionId || !username || !isLoggedIn(),
|
|
188415
|
+
});
|
|
188416
|
+
const vectorDocuments = hasOwnDocuments
|
|
188417
|
+
? (documents !== null && documents !== void 0 ? documents : undefined)
|
|
188418
|
+
: sessionDocuments;
|
|
188419
|
+
useEffect(() => {
|
|
188420
|
+
if (!hasOwnDocuments && !isStreaming && isLoggedIn() && status !== 'uninitialized') {
|
|
188421
|
+
refetch();
|
|
188422
|
+
}
|
|
188423
|
+
}, [hasOwnDocuments, isStreaming, refetch]);
|
|
188424
|
+
if (!(vectorDocuments === null || vectorDocuments === void 0 ? void 0 : vectorDocuments.length)) {
|
|
188425
|
+
return null;
|
|
188426
|
+
}
|
|
188427
|
+
return (jsxs(Fragment$1, { children: [jsxs(Button$1, { variant: "outline", size: "sm", className: cn('flex items-center gap-2 border-gray-200 bg-white text-gray-700 hover:bg-gray-50', className), onClick: (event) => {
|
|
188428
|
+
// Safe inside clickable transcript rows: the row must not react.
|
|
188429
|
+
event.stopPropagation();
|
|
188430
|
+
setIsOpen(true);
|
|
188431
|
+
}, "data-testid": "retrieved-documents-button", children: [jsx(FileText, { className: "h-4 w-4 text-blue-600" }), jsx("span", { children: label !== null && label !== void 0 ? label : 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: "min-h-0 flex-1 overflow-y-auto", "data-testid": "retrieved-documents-scroll", children: jsx(DocumentSidebar, { isModal: true, sessionId: sessionId, documents: documents }) })] }) })] }));
|
|
188432
|
+
}
|
|
188433
|
+
|
|
188434
|
+
var COLLAPSIBLE_NAME = "Collapsible";
|
|
188435
|
+
var [createCollapsibleContext] = createContextScope$1(COLLAPSIBLE_NAME);
|
|
188436
|
+
var [CollapsibleProvider, useCollapsibleContext] = createCollapsibleContext(COLLAPSIBLE_NAME);
|
|
188437
|
+
var Collapsible$1 = React.forwardRef(
|
|
188438
|
+
(props, forwardedRef) => {
|
|
188439
|
+
const {
|
|
188440
|
+
__scopeCollapsible,
|
|
188441
|
+
open: openProp,
|
|
188442
|
+
defaultOpen,
|
|
188443
|
+
disabled,
|
|
188444
|
+
onOpenChange,
|
|
188445
|
+
...collapsibleProps
|
|
188446
|
+
} = props;
|
|
188447
|
+
const [open, setOpen] = useControllableState$2({
|
|
188448
|
+
prop: openProp,
|
|
188449
|
+
defaultProp: defaultOpen ?? false,
|
|
188450
|
+
onChange: onOpenChange,
|
|
188451
|
+
caller: COLLAPSIBLE_NAME
|
|
188452
|
+
});
|
|
188453
|
+
return /* @__PURE__ */ jsx(
|
|
188454
|
+
CollapsibleProvider,
|
|
188455
|
+
{
|
|
188456
|
+
scope: __scopeCollapsible,
|
|
188457
|
+
disabled,
|
|
188458
|
+
contentId: useId$1(),
|
|
188459
|
+
open,
|
|
188460
|
+
onOpenToggle: React.useCallback(() => setOpen((prevOpen) => !prevOpen), [setOpen]),
|
|
188461
|
+
children: /* @__PURE__ */ jsx(
|
|
188462
|
+
Primitive$4.div,
|
|
188463
|
+
{
|
|
188464
|
+
"data-state": getState$1(open),
|
|
188465
|
+
"data-disabled": disabled ? "" : void 0,
|
|
188466
|
+
...collapsibleProps,
|
|
188467
|
+
ref: forwardedRef
|
|
188468
|
+
}
|
|
188469
|
+
)
|
|
188470
|
+
}
|
|
188471
|
+
);
|
|
188472
|
+
}
|
|
188473
|
+
);
|
|
188474
|
+
Collapsible$1.displayName = COLLAPSIBLE_NAME;
|
|
188475
|
+
var TRIGGER_NAME$1 = "CollapsibleTrigger";
|
|
188476
|
+
var CollapsibleTrigger$1 = React.forwardRef(
|
|
188477
|
+
(props, forwardedRef) => {
|
|
188478
|
+
const { __scopeCollapsible, ...triggerProps } = props;
|
|
188479
|
+
const context = useCollapsibleContext(TRIGGER_NAME$1, __scopeCollapsible);
|
|
188480
|
+
return /* @__PURE__ */ jsx(
|
|
188481
|
+
Primitive$4.button,
|
|
188482
|
+
{
|
|
188483
|
+
type: "button",
|
|
188484
|
+
"aria-controls": context.contentId,
|
|
188485
|
+
"aria-expanded": context.open || false,
|
|
188486
|
+
"data-state": getState$1(context.open),
|
|
188487
|
+
"data-disabled": context.disabled ? "" : void 0,
|
|
188488
|
+
disabled: context.disabled,
|
|
188489
|
+
...triggerProps,
|
|
188490
|
+
ref: forwardedRef,
|
|
188491
|
+
onClick: composeEventHandlers$2(props.onClick, context.onOpenToggle)
|
|
188492
|
+
}
|
|
188493
|
+
);
|
|
188494
|
+
}
|
|
188495
|
+
);
|
|
188496
|
+
CollapsibleTrigger$1.displayName = TRIGGER_NAME$1;
|
|
188497
|
+
var CONTENT_NAME$1 = "CollapsibleContent";
|
|
188498
|
+
var CollapsibleContent$1 = React.forwardRef(
|
|
188499
|
+
(props, forwardedRef) => {
|
|
188500
|
+
const { forceMount, ...contentProps } = props;
|
|
188501
|
+
const context = useCollapsibleContext(CONTENT_NAME$1, props.__scopeCollapsible);
|
|
188502
|
+
return /* @__PURE__ */ jsx(Presence$2, { present: forceMount || context.open, children: ({ present }) => /* @__PURE__ */ jsx(CollapsibleContentImpl, { ...contentProps, ref: forwardedRef, present }) });
|
|
188503
|
+
}
|
|
188504
|
+
);
|
|
188505
|
+
CollapsibleContent$1.displayName = CONTENT_NAME$1;
|
|
188506
|
+
var CollapsibleContentImpl = React.forwardRef((props, forwardedRef) => {
|
|
188507
|
+
const { __scopeCollapsible, present, children, ...contentProps } = props;
|
|
188508
|
+
const context = useCollapsibleContext(CONTENT_NAME$1, __scopeCollapsible);
|
|
188509
|
+
const [isPresent, setIsPresent] = React.useState(present);
|
|
188510
|
+
const ref = React.useRef(null);
|
|
188511
|
+
const composedRefs = useComposedRefs$1(forwardedRef, ref);
|
|
188512
|
+
const heightRef = React.useRef(0);
|
|
188513
|
+
const height = heightRef.current;
|
|
188514
|
+
const widthRef = React.useRef(0);
|
|
188515
|
+
const width = widthRef.current;
|
|
188516
|
+
const isOpen = context.open || isPresent;
|
|
188517
|
+
const isMountAnimationPreventedRef = React.useRef(isOpen);
|
|
188518
|
+
const originalStylesRef = React.useRef(void 0);
|
|
188519
|
+
React.useEffect(() => {
|
|
188520
|
+
const rAF = requestAnimationFrame(() => isMountAnimationPreventedRef.current = false);
|
|
188521
|
+
return () => cancelAnimationFrame(rAF);
|
|
188522
|
+
}, []);
|
|
188523
|
+
useLayoutEffect2$1(() => {
|
|
188524
|
+
const node = ref.current;
|
|
188525
|
+
if (node) {
|
|
188526
|
+
originalStylesRef.current = originalStylesRef.current || {
|
|
188527
|
+
transitionDuration: node.style.transitionDuration,
|
|
188528
|
+
animationName: node.style.animationName
|
|
188529
|
+
};
|
|
188530
|
+
node.style.transitionDuration = "0s";
|
|
188531
|
+
node.style.animationName = "none";
|
|
188532
|
+
const rect = node.getBoundingClientRect();
|
|
188533
|
+
heightRef.current = rect.height;
|
|
188534
|
+
widthRef.current = rect.width;
|
|
188535
|
+
if (!isMountAnimationPreventedRef.current) {
|
|
188536
|
+
node.style.transitionDuration = originalStylesRef.current.transitionDuration;
|
|
188537
|
+
node.style.animationName = originalStylesRef.current.animationName;
|
|
188538
|
+
}
|
|
188539
|
+
setIsPresent(present);
|
|
188540
|
+
}
|
|
188541
|
+
}, [context.open, present]);
|
|
188542
|
+
return /* @__PURE__ */ jsx(
|
|
188543
|
+
Primitive$4.div,
|
|
188544
|
+
{
|
|
188545
|
+
"data-state": getState$1(context.open),
|
|
188546
|
+
"data-disabled": context.disabled ? "" : void 0,
|
|
188547
|
+
id: context.contentId,
|
|
188548
|
+
hidden: !isOpen,
|
|
188549
|
+
...contentProps,
|
|
188550
|
+
ref: composedRefs,
|
|
188551
|
+
style: {
|
|
188552
|
+
[`--radix-collapsible-content-height`]: height ? `${height}px` : void 0,
|
|
188553
|
+
[`--radix-collapsible-content-width`]: width ? `${width}px` : void 0,
|
|
188554
|
+
...props.style
|
|
188555
|
+
},
|
|
188556
|
+
children: isOpen && children
|
|
188557
|
+
}
|
|
188558
|
+
);
|
|
188559
|
+
});
|
|
188560
|
+
function getState$1(open) {
|
|
188561
|
+
return open ? "open" : "closed";
|
|
188562
|
+
}
|
|
188563
|
+
var Root$3 = Collapsible$1;
|
|
188564
|
+
|
|
188565
|
+
const Collapsible = Root$3;
|
|
188566
|
+
const CollapsibleTrigger = CollapsibleTrigger$1;
|
|
188567
|
+
const CollapsibleContent = CollapsibleContent$1;
|
|
188568
|
+
|
|
188569
|
+
function getFriendlyToolName(toolName) {
|
|
188570
|
+
if (TOOL_NAME_MAP === null || TOOL_NAME_MAP === void 0 ? void 0 : TOOL_NAME_MAP[toolName])
|
|
188571
|
+
return TOOL_NAME_MAP[toolName];
|
|
188572
|
+
const words = toolName.replace(/_/g, ' ').trim();
|
|
188573
|
+
return words.charAt(0).toUpperCase() + words.slice(1);
|
|
188574
|
+
}
|
|
188575
|
+
// Extract a short human-readable query from tool input or log
|
|
188576
|
+
function getQueryLabel(toolCall) {
|
|
188577
|
+
var _a, _b, _c, _d, _e;
|
|
188578
|
+
// Prefer structured input
|
|
188579
|
+
if (toolCall.input && typeof toolCall.input === 'object') {
|
|
188580
|
+
const val = (_c = (_b = (_a = toolCall.input.query) !== null && _a !== void 0 ? _a : toolCall.input.q) !== null && _b !== void 0 ? _b : toolCall.input.input) !== null && _c !== void 0 ? _c : toolCall.input.text;
|
|
188581
|
+
if (val && typeof val === 'string')
|
|
188582
|
+
return val;
|
|
188583
|
+
// Fallback: first string value in input
|
|
188584
|
+
const firstStr = Object.values(toolCall.input).find((v) => typeof v === 'string');
|
|
188585
|
+
if (firstStr)
|
|
188586
|
+
return firstStr;
|
|
188587
|
+
}
|
|
188588
|
+
// Fallback: parse the "… with `{...}`" snippet of the log string. Located
|
|
188589
|
+
// with index scans rather than a lazy regex, which backtracks
|
|
188590
|
+
// polynomially on adversarial logs (CodeQL js/polynomial-redos).
|
|
188591
|
+
if (toolCall.log) {
|
|
188592
|
+
const snippet = extractLogPayload(toolCall.log);
|
|
188593
|
+
if (snippet) {
|
|
188594
|
+
try {
|
|
188595
|
+
const parsed = JSON.parse(snippet.replace(/'/g, '"'));
|
|
188596
|
+
const val = (_e = (_d = parsed.query) !== null && _d !== void 0 ? _d : parsed.q) !== null && _e !== void 0 ? _e : parsed.input;
|
|
188597
|
+
if (val)
|
|
188598
|
+
return val;
|
|
188599
|
+
}
|
|
188600
|
+
catch (_f) {
|
|
188601
|
+
// Not every log snippet is JSON (apostrophes inside the payload break
|
|
188602
|
+
// the quote swap above). That is expected input, not an error — and
|
|
188603
|
+
// this runs inside a memo comparator on every streaming tick, so
|
|
188604
|
+
// logging here flooded the console on phones.
|
|
188605
|
+
}
|
|
188606
|
+
}
|
|
188607
|
+
}
|
|
188608
|
+
return null;
|
|
188609
|
+
}
|
|
188610
|
+
/** The `{...}` inside the first "with `{...}`" of a tool log, or null. */
|
|
188611
|
+
function extractLogPayload(log) {
|
|
188612
|
+
let from = 0;
|
|
188613
|
+
while (from < log.length) {
|
|
188614
|
+
const open = log.indexOf('`{', from);
|
|
188615
|
+
if (open === -1)
|
|
188616
|
+
return null;
|
|
188617
|
+
// Must follow the word "with" plus at least one whitespace character.
|
|
188618
|
+
let i = open - 1;
|
|
188619
|
+
let sawSpace = false;
|
|
188620
|
+
while (i >= 0 && /\s/.test(log[i])) {
|
|
188621
|
+
sawSpace = true;
|
|
188622
|
+
i -= 1;
|
|
188623
|
+
}
|
|
188624
|
+
if (sawSpace && log.slice(Math.max(0, i - 3), i + 1) === 'with') {
|
|
188625
|
+
const close = log.indexOf('}`', open + 1);
|
|
188626
|
+
if (close === -1)
|
|
188627
|
+
return null;
|
|
188628
|
+
return log.slice(open + 1, close + 1);
|
|
188629
|
+
}
|
|
188630
|
+
from = open + 1;
|
|
188631
|
+
}
|
|
188632
|
+
return null;
|
|
188633
|
+
}
|
|
188634
|
+
function formatResult(result) {
|
|
188635
|
+
return result.replace(/\n{3,}/g, '\n\n').trim();
|
|
188636
|
+
}
|
|
188637
|
+
|
|
188638
|
+
const TOOL_ICONS = {
|
|
188639
|
+
web_search_call: Globe,
|
|
188640
|
+
vector_search: Search,
|
|
188641
|
+
code_executor: Code$1,
|
|
188642
|
+
file_reader: FileText,
|
|
188643
|
+
wikipedia: BookOpen,
|
|
188644
|
+
};
|
|
188645
|
+
function getToolIcon(toolName) {
|
|
188646
|
+
return (toolName && TOOL_ICONS[toolName]) || Wrench;
|
|
188647
|
+
}
|
|
188648
|
+
/**
|
|
188649
|
+
* Collapsible record of the tools a turn used — the "Used N tools" line of
|
|
188650
|
+
* the chat bubble.
|
|
188651
|
+
*
|
|
188652
|
+
* The header always reads as the completed record ("Used N tools") and the
|
|
188653
|
+
* individual rows never animate. Only while this row is the live phase does the
|
|
188654
|
+
* header sprout dots — at which point the working line has stood down, so there
|
|
188655
|
+
* is still exactly one animated "agent is working" signal on screen.
|
|
188656
|
+
*/
|
|
188657
|
+
function ToolCallIndicator({ toolCalls, isActive = false, showResults = false, }) {
|
|
188658
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
188659
|
+
// `write_todos` has a dedicated renderer (`AgentTodoList`), so it must never
|
|
188660
|
+
// appear as a generic tool card nor be counted in "Used N tools".
|
|
188661
|
+
const visibleToolCalls = (toolCalls !== null && toolCalls !== void 0 ? toolCalls : []).filter((tc) => (tc === null || tc === void 0 ? void 0 : tc.name) !== WRITE_TODOS_TOOL);
|
|
188662
|
+
if (visibleToolCalls.length === 0) {
|
|
188663
|
+
return null;
|
|
188664
|
+
}
|
|
188665
|
+
const uniqueToolCount = new Set(visibleToolCalls.map((tc) => tc.name)).size;
|
|
188666
|
+
const headerLabel = `Used ${uniqueToolCount} tool${uniqueToolCount === 1 ? '' : 's'}`;
|
|
188667
|
+
return (jsxs(Collapsible, { open: isOpen, onOpenChange: setIsOpen, className: "mb-2", children: [jsxs(CollapsibleTrigger, { className: "flex cursor-pointer items-center gap-1 pt-1 text-xs text-gray-600 transition-colors hover:text-gray-800", children: [jsx(ChevronRight, { className: cn('h-3 w-3 transition-transform duration-200', isOpen && 'rotate-90') }), jsx(Wrench, { className: "h-3 w-3" }), jsx("span", { children: headerLabel }), isActive && (jsxs("span", { className: "inline-flex gap-0.5", "aria-hidden": "true", children: [jsx("span", { className: "inline-block h-1 w-1 animate-bounce rounded-full bg-gray-600 [animation-delay:0ms] motion-reduce:animate-none" }), jsx("span", { className: "inline-block h-1 w-1 animate-bounce rounded-full bg-gray-600 [animation-delay:150ms] motion-reduce:animate-none" }), jsx("span", { className: "inline-block h-1 w-1 animate-bounce rounded-full bg-gray-600 [animation-delay:300ms] motion-reduce:animate-none" })] }))] }), jsx(CollapsibleContent, { className: "pb-2 pl-4", children: jsx("div", { className: "space-y-2.5 border-l-2 border-gray-300 pt-2.5 pl-3 text-xs leading-relaxed text-gray-600", children: visibleToolCalls.map((toolCall, index) => {
|
|
188668
|
+
var _a;
|
|
188669
|
+
const query = getQueryLabel(toolCall);
|
|
188670
|
+
const Icon = getToolIcon(toolCall === null || toolCall === void 0 ? void 0 : toolCall.name);
|
|
188671
|
+
const result = showResults && (toolCall === null || toolCall === void 0 ? void 0 : toolCall.result) ? formatResult(toolCall.result) : null;
|
|
188672
|
+
return (jsxs("div", { children: [jsxs("div", { className: "flex items-center gap-1.5 text-gray-700", children: [jsx(Icon, { className: "h-3 w-3 shrink-0 text-gray-500" }), jsx("span", { className: "font-medium", children: getFriendlyToolName((_a = toolCall === null || toolCall === void 0 ? void 0 : toolCall.name) !== null && _a !== void 0 ? _a : '') })] }), query && (jsx("div", { className: "mt-0.5 ml-[18px] text-gray-600", children: jsx(Markdown, { className: "prose prose-xs max-w-none [&_*]:text-xs [&_*]:text-gray-600 [&_p]:m-0", children: query }) })), result && (jsx("div", { className: "mt-1 ml-[18px] max-h-48 overflow-y-auto rounded-md border border-gray-200 bg-white px-2 py-1.5 leading-relaxed whitespace-pre-wrap text-gray-600", "data-testid": "tool-call-result", children: result }))] }, (toolCall === null || toolCall === void 0 ? void 0 : toolCall.id) || index));
|
|
188673
|
+
}) }) })] }));
|
|
188674
|
+
}
|
|
188675
|
+
|
|
188676
|
+
/**
|
|
188677
|
+
* A model the way the nav bar shows the mentor's: the provider logo in a
|
|
188678
|
+
* white circle (the catalogue's artwork, or the bot icon when it has none)
|
|
188679
|
+
* beside the model's display name. Read-only; used on admin transcripts to
|
|
188680
|
+
* name the model a turn ran on.
|
|
188681
|
+
*/
|
|
188682
|
+
function LlmModelBadge({ model, provider, tenantKey, mentorId, className, }) {
|
|
188683
|
+
var _a, _b;
|
|
188684
|
+
const params = useParams();
|
|
188685
|
+
const username = useUsername();
|
|
188686
|
+
const org = (_a = tenantKey !== null && tenantKey !== void 0 ? tenantKey : params === null || params === void 0 ? void 0 : params.tenantKey) !== null && _a !== void 0 ? _a : null;
|
|
188687
|
+
const mentor = (_b = mentorId !== null && mentorId !== void 0 ? mentorId : params === null || params === void 0 ? void 0 : params.mentorId) !== null && _b !== void 0 ? _b : null;
|
|
188688
|
+
const resolveLlmProvider = useLlmProviderCatalogue({ org, userId: username, mentorId: mentor });
|
|
188689
|
+
// With no provider key (transcript rows carry only the model), the
|
|
188690
|
+
// catalogue row that lists this model supplies the logo and name.
|
|
188691
|
+
const providerDetails = resolveLlmProvider(provider, model);
|
|
188692
|
+
const displayName = useLlmDisplayName({
|
|
188693
|
+
llmName: model,
|
|
188694
|
+
org,
|
|
188695
|
+
userId: username,
|
|
188696
|
+
mentorId: mentor,
|
|
188697
|
+
});
|
|
188698
|
+
const label = displayName || providerDetails.displayName;
|
|
188699
|
+
if (!label)
|
|
188700
|
+
return null;
|
|
188701
|
+
return (jsxs("span", { className: cn('inline-flex max-w-full items-center gap-2 text-sm font-medium text-[#646464]', className), title: providerDetails.displayName && providerDetails.displayName !== label
|
|
188702
|
+
? `${label} · ${providerDetails.displayName}`
|
|
188703
|
+
: label, "data-testid": "llm-model-badge", children: [jsx("span", { className: "flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-full bg-white", children: providerDetails.logo ? (jsx("img", { src: providerDetails.logo, alt: `${label} model logo`, className: "h-5 w-5 object-contain", height: 32, width: 32, loading: "lazy" })) : (jsx(Bot, { className: "h-4 w-4", "aria-hidden": "true" })) }), jsx("span", { className: "max-w-[220px] truncate", children: label })] }));
|
|
188704
|
+
}
|
|
188705
|
+
|
|
188706
|
+
/** SPAs whose users have coursework, so the profile leads with a Gradebook tab. */
|
|
188707
|
+
const GRADEBOOK_SPAS = ['lms', 'skills'];
|
|
188708
|
+
/**
|
|
188709
|
+
* The customization `Profile` is opened with: whatever the host passed, with
|
|
188710
|
+
* the Gradebook tab defaulted from the SPA it runs in. An explicit
|
|
188711
|
+
* `showGradebookTab` always wins, so a host can force it either way.
|
|
188712
|
+
*/
|
|
188713
|
+
function profileCustomization(customization, currentSPA) {
|
|
188714
|
+
var _a;
|
|
188715
|
+
return {
|
|
188716
|
+
...customization,
|
|
188717
|
+
showGradebookTab: (_a = customization === null || customization === void 0 ? void 0 : customization.showGradebookTab) !== null && _a !== void 0 ? _a : GRADEBOOK_SPAS.includes((currentSPA !== null && currentSPA !== void 0 ? currentSPA : '').trim().toLowerCase()),
|
|
188718
|
+
};
|
|
188719
|
+
}
|
|
188720
|
+
/**
|
|
188721
|
+
* The shared `Profile` viewer in a dialog — the same modal the tenant
|
|
188722
|
+
* Management tab opens when a user row is clicked. Controlled variant for
|
|
188723
|
+
* hosts that trigger it from a whole table row.
|
|
188724
|
+
*
|
|
188725
|
+
* Radix portals the dialog into `document.body`, but a React portal still
|
|
188726
|
+
* bubbles its events through the React tree — so without the guard below, a
|
|
188727
|
+
* click *inside* the open profile would reach the row this dialog is rendered
|
|
188728
|
+
* from and fire its `onClick` (e.g. opening the enrollment progress modal
|
|
188729
|
+
* behind the profile). The wrapper is `display: contents`, so it adds nothing
|
|
188730
|
+
* to the host's layout.
|
|
188731
|
+
*/
|
|
188732
|
+
function UserProfileDialog({ tenantKey, username, isOpen, onClose, customization, currentSPA, }) {
|
|
188733
|
+
const t = useT();
|
|
188734
|
+
if (!isOpen)
|
|
188735
|
+
return null;
|
|
188736
|
+
return (jsx("span", { className: "contents", onClick: (event) => event.stopPropagation(), onMouseDown: (event) => event.stopPropagation(), onKeyDown: (event) => event.stopPropagation(), children: jsx(Dialog, { open: true, onOpenChange: onClose, children: jsxs(DialogContent, { autoFocus: false, className: "profile-component-dialog max-w-7xl w-[85vw] gap-0 overflow-hidden bg-white p-0", style: { height: '85vh', display: 'flex', flexDirection: 'column' }, "data-testid": "user-profile-link-dialog", children: [jsx(DialogTitle, { className: "sr-only", children: t('tabsUserstab.profileDialogTitle') }), jsx(DialogDescription, { className: "sr-only", children: t('tabsUserstab.profileDialogDescription') }), jsx(Profile, { tenant: tenantKey, tenants: [], username: username, onClose: onClose, customization: profileCustomization(customization, currentSPA), currentSPA: currentSPA })] }) }) }));
|
|
188737
|
+
}
|
|
188738
|
+
/**
|
|
188739
|
+
* Clickable user identity that opens the shared `Profile` viewer in a dialog
|
|
188740
|
+
* — the same modal the tenant Management tab opens when a user row is
|
|
188741
|
+
* clicked. `Profile` drops into preview (read-only) mode on its own for anyone
|
|
188742
|
+
* but the signed-in user. Used by the spend-cap tables and every analytics
|
|
188743
|
+
* surface that names a user; safe inside clickable rows and cards, since
|
|
188744
|
+
* neither its clicks nor its key presses reach the host's handlers.
|
|
188745
|
+
*/
|
|
188746
|
+
function UserProfileLink({ tenantKey, username, display, className, testId, customization, currentSPA, }) {
|
|
188747
|
+
const t = useT();
|
|
188748
|
+
const [isOpen, setIsOpen] = React__default.useState(false);
|
|
188749
|
+
if (!username) {
|
|
188750
|
+
// `inline-block`, or `truncate`'s `overflow: hidden` has nothing to clip:
|
|
188751
|
+
// an inline box takes its width from its own text.
|
|
188752
|
+
return (jsx("span", { className: cn('inline-block max-w-full truncate', className), "data-testid": testId, children: display }));
|
|
188753
|
+
}
|
|
188754
|
+
return (jsxs(Fragment$1, { children: [jsx("button", { type: "button", onClick: (event) => {
|
|
188755
|
+
event.stopPropagation();
|
|
188756
|
+
setIsOpen(true);
|
|
188757
|
+
},
|
|
188758
|
+
// Rows that open on Enter/Space would otherwise swallow the key press.
|
|
188759
|
+
onKeyDown: (event) => event.stopPropagation(), className: cn('max-w-full cursor-pointer truncate text-left hover:text-blue-600 hover:underline focus:text-blue-600 focus:outline-none', className), "aria-label": t('tabsUserstab.viewProfileAriaLabel', { name: display }), "data-testid": testId, children: display }), jsx(UserProfileDialog, { tenantKey: tenantKey, username: username, isOpen: isOpen, onClose: () => setIsOpen(false), customization: customization, currentSPA: currentSPA })] }));
|
|
188760
|
+
}
|
|
188761
|
+
|
|
187914
188762
|
const AdvancedPagination = ({ currentPage, totalPages, onPageChange, totalCount, itemsPerPage, itemLabel = 'items', variant = 'default', className, }) => {
|
|
187915
188763
|
const t = useT();
|
|
187916
188764
|
if (totalPages <= 1) {
|
|
@@ -189821,141 +190669,6 @@ function trimTrailingSlashes(value) {
|
|
|
189821
190669
|
return end === value.length ? value : value.slice(0, end);
|
|
189822
190670
|
}
|
|
189823
190671
|
|
|
189824
|
-
var COLLAPSIBLE_NAME = "Collapsible";
|
|
189825
|
-
var [createCollapsibleContext] = createContextScope$1(COLLAPSIBLE_NAME);
|
|
189826
|
-
var [CollapsibleProvider, useCollapsibleContext] = createCollapsibleContext(COLLAPSIBLE_NAME);
|
|
189827
|
-
var Collapsible$1 = React.forwardRef(
|
|
189828
|
-
(props, forwardedRef) => {
|
|
189829
|
-
const {
|
|
189830
|
-
__scopeCollapsible,
|
|
189831
|
-
open: openProp,
|
|
189832
|
-
defaultOpen,
|
|
189833
|
-
disabled,
|
|
189834
|
-
onOpenChange,
|
|
189835
|
-
...collapsibleProps
|
|
189836
|
-
} = props;
|
|
189837
|
-
const [open, setOpen] = useControllableState$2({
|
|
189838
|
-
prop: openProp,
|
|
189839
|
-
defaultProp: defaultOpen ?? false,
|
|
189840
|
-
onChange: onOpenChange,
|
|
189841
|
-
caller: COLLAPSIBLE_NAME
|
|
189842
|
-
});
|
|
189843
|
-
return /* @__PURE__ */ jsx(
|
|
189844
|
-
CollapsibleProvider,
|
|
189845
|
-
{
|
|
189846
|
-
scope: __scopeCollapsible,
|
|
189847
|
-
disabled,
|
|
189848
|
-
contentId: useId$1(),
|
|
189849
|
-
open,
|
|
189850
|
-
onOpenToggle: React.useCallback(() => setOpen((prevOpen) => !prevOpen), [setOpen]),
|
|
189851
|
-
children: /* @__PURE__ */ jsx(
|
|
189852
|
-
Primitive$4.div,
|
|
189853
|
-
{
|
|
189854
|
-
"data-state": getState$1(open),
|
|
189855
|
-
"data-disabled": disabled ? "" : void 0,
|
|
189856
|
-
...collapsibleProps,
|
|
189857
|
-
ref: forwardedRef
|
|
189858
|
-
}
|
|
189859
|
-
)
|
|
189860
|
-
}
|
|
189861
|
-
);
|
|
189862
|
-
}
|
|
189863
|
-
);
|
|
189864
|
-
Collapsible$1.displayName = COLLAPSIBLE_NAME;
|
|
189865
|
-
var TRIGGER_NAME$1 = "CollapsibleTrigger";
|
|
189866
|
-
var CollapsibleTrigger$1 = React.forwardRef(
|
|
189867
|
-
(props, forwardedRef) => {
|
|
189868
|
-
const { __scopeCollapsible, ...triggerProps } = props;
|
|
189869
|
-
const context = useCollapsibleContext(TRIGGER_NAME$1, __scopeCollapsible);
|
|
189870
|
-
return /* @__PURE__ */ jsx(
|
|
189871
|
-
Primitive$4.button,
|
|
189872
|
-
{
|
|
189873
|
-
type: "button",
|
|
189874
|
-
"aria-controls": context.contentId,
|
|
189875
|
-
"aria-expanded": context.open || false,
|
|
189876
|
-
"data-state": getState$1(context.open),
|
|
189877
|
-
"data-disabled": context.disabled ? "" : void 0,
|
|
189878
|
-
disabled: context.disabled,
|
|
189879
|
-
...triggerProps,
|
|
189880
|
-
ref: forwardedRef,
|
|
189881
|
-
onClick: composeEventHandlers$2(props.onClick, context.onOpenToggle)
|
|
189882
|
-
}
|
|
189883
|
-
);
|
|
189884
|
-
}
|
|
189885
|
-
);
|
|
189886
|
-
CollapsibleTrigger$1.displayName = TRIGGER_NAME$1;
|
|
189887
|
-
var CONTENT_NAME$1 = "CollapsibleContent";
|
|
189888
|
-
var CollapsibleContent$1 = React.forwardRef(
|
|
189889
|
-
(props, forwardedRef) => {
|
|
189890
|
-
const { forceMount, ...contentProps } = props;
|
|
189891
|
-
const context = useCollapsibleContext(CONTENT_NAME$1, props.__scopeCollapsible);
|
|
189892
|
-
return /* @__PURE__ */ jsx(Presence$2, { present: forceMount || context.open, children: ({ present }) => /* @__PURE__ */ jsx(CollapsibleContentImpl, { ...contentProps, ref: forwardedRef, present }) });
|
|
189893
|
-
}
|
|
189894
|
-
);
|
|
189895
|
-
CollapsibleContent$1.displayName = CONTENT_NAME$1;
|
|
189896
|
-
var CollapsibleContentImpl = React.forwardRef((props, forwardedRef) => {
|
|
189897
|
-
const { __scopeCollapsible, present, children, ...contentProps } = props;
|
|
189898
|
-
const context = useCollapsibleContext(CONTENT_NAME$1, __scopeCollapsible);
|
|
189899
|
-
const [isPresent, setIsPresent] = React.useState(present);
|
|
189900
|
-
const ref = React.useRef(null);
|
|
189901
|
-
const composedRefs = useComposedRefs$1(forwardedRef, ref);
|
|
189902
|
-
const heightRef = React.useRef(0);
|
|
189903
|
-
const height = heightRef.current;
|
|
189904
|
-
const widthRef = React.useRef(0);
|
|
189905
|
-
const width = widthRef.current;
|
|
189906
|
-
const isOpen = context.open || isPresent;
|
|
189907
|
-
const isMountAnimationPreventedRef = React.useRef(isOpen);
|
|
189908
|
-
const originalStylesRef = React.useRef(void 0);
|
|
189909
|
-
React.useEffect(() => {
|
|
189910
|
-
const rAF = requestAnimationFrame(() => isMountAnimationPreventedRef.current = false);
|
|
189911
|
-
return () => cancelAnimationFrame(rAF);
|
|
189912
|
-
}, []);
|
|
189913
|
-
useLayoutEffect2$1(() => {
|
|
189914
|
-
const node = ref.current;
|
|
189915
|
-
if (node) {
|
|
189916
|
-
originalStylesRef.current = originalStylesRef.current || {
|
|
189917
|
-
transitionDuration: node.style.transitionDuration,
|
|
189918
|
-
animationName: node.style.animationName
|
|
189919
|
-
};
|
|
189920
|
-
node.style.transitionDuration = "0s";
|
|
189921
|
-
node.style.animationName = "none";
|
|
189922
|
-
const rect = node.getBoundingClientRect();
|
|
189923
|
-
heightRef.current = rect.height;
|
|
189924
|
-
widthRef.current = rect.width;
|
|
189925
|
-
if (!isMountAnimationPreventedRef.current) {
|
|
189926
|
-
node.style.transitionDuration = originalStylesRef.current.transitionDuration;
|
|
189927
|
-
node.style.animationName = originalStylesRef.current.animationName;
|
|
189928
|
-
}
|
|
189929
|
-
setIsPresent(present);
|
|
189930
|
-
}
|
|
189931
|
-
}, [context.open, present]);
|
|
189932
|
-
return /* @__PURE__ */ jsx(
|
|
189933
|
-
Primitive$4.div,
|
|
189934
|
-
{
|
|
189935
|
-
"data-state": getState$1(context.open),
|
|
189936
|
-
"data-disabled": context.disabled ? "" : void 0,
|
|
189937
|
-
id: context.contentId,
|
|
189938
|
-
hidden: !isOpen,
|
|
189939
|
-
...contentProps,
|
|
189940
|
-
ref: composedRefs,
|
|
189941
|
-
style: {
|
|
189942
|
-
[`--radix-collapsible-content-height`]: height ? `${height}px` : void 0,
|
|
189943
|
-
[`--radix-collapsible-content-width`]: width ? `${width}px` : void 0,
|
|
189944
|
-
...props.style
|
|
189945
|
-
},
|
|
189946
|
-
children: isOpen && children
|
|
189947
|
-
}
|
|
189948
|
-
);
|
|
189949
|
-
});
|
|
189950
|
-
function getState$1(open) {
|
|
189951
|
-
return open ? "open" : "closed";
|
|
189952
|
-
}
|
|
189953
|
-
var Root$3 = Collapsible$1;
|
|
189954
|
-
|
|
189955
|
-
const Collapsible = Root$3;
|
|
189956
|
-
const CollapsibleTrigger = CollapsibleTrigger$1;
|
|
189957
|
-
const CollapsibleContent = CollapsibleContent$1;
|
|
189958
|
-
|
|
189959
190672
|
// Pure logic behind the application form (questions) editor. No React here so
|
|
189960
190673
|
// it stays unit testable. The backend validates schemas on save and remains
|
|
189961
190674
|
// authoritative; these helpers only shape the editor's local state.
|
|
@@ -194258,62 +194971,6 @@ function SpendLimitsSection({ tenantKey, labels: labelsOverride }) {
|
|
|
194258
194971
|
return (jsxs(Fragment$1, { children: [jsxs("div", { "data-testid": "spend-limits-workspace-section", className: "rounded-lg border border-[#e5e5e5] bg-white shadow-[0_1px_2px_0_rgba(0,0,0,0.05)] dark:bg-zinc-900 dark:border-zinc-800", children: [jsx("div", { className: "flex flex-col gap-2 p-4 sm:flex-row sm:items-start sm:justify-between", children: jsxs("div", { className: "space-y-0.5", children: [jsx("h3", { className: "text-[16px] font-medium leading-6 text-[#101828] dark:text-gray-100", children: labels.tenantSections.workspace.title }), jsx("p", { className: "text-[13px] font-normal leading-5 text-[#4a5565] dark:text-gray-400", children: labels.tenantSections.workspace.description })] }) }), jsx("div", { className: "border-t border-[#e5e7eb] dark:border-zinc-800 px-4 py-3", children: isTenantCapLoading ? (jsx("div", { className: "flex items-center justify-center py-8", "data-testid": "tenant-cap-loading", children: jsx(Spinner, {}) })) : isTenantForbidden ? (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": "spend-limits-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("div", { className: "space-y-4", children: [!tenantCap && (monthlySpend != null || totalSpend != null) && (jsxs("div", { className: "space-y-1", "data-testid": "workspace-actual-spend-stats", children: [jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [monthlySpend != null && (jsxs("div", { className: "space-y-0.5", children: [jsx("p", { className: "text-[11px] font-medium uppercase tracking-wide text-[#6a7282] dark:text-gray-400", children: labels.tenantSections.noCapStats.spentThisMonth }), jsx("p", { className: "text-[18px] font-semibold leading-6 text-[#101828] dark:text-gray-100", "data-testid": "workspace-actual-spend-month", children: formatUsd$2(String(monthlySpend)) })] })), totalSpend != null && (jsxs("div", { className: "space-y-0.5", children: [jsx("p", { className: "text-[11px] font-medium uppercase tracking-wide text-[#6a7282] dark:text-gray-400", children: labels.tenantSections.noCapStats.spentAllTime }), jsx("p", { className: "text-[18px] font-semibold leading-6 text-[#101828] dark:text-gray-100", "data-testid": "workspace-actual-spend-total", children: formatUsd$2(String(totalSpend)) })] }))] }), jsx("p", { className: "text-[12px] font-normal leading-4 text-[#6a7282] dark:text-gray-500", children: labels.tenantSections.noCapStats.hint })] })), jsx(SpendCapForm, { labels: labels, cap: tenantCap, isSaving: isSavingTenantCap, isDeleting: isDeletingTenantCap, onSave: saveTenantCap, onDelete: () => setIsDeleteOpen(true), testId: "tenant-cap" })] })) })] }), jsx(Dialog, { open: isDeleteOpen, onOpenChange: () => setIsDeleteOpen(false), children: jsxs(DialogContent, { "aria-describedby": "tenant-cap-delete-description", "data-testid": "tenant-cap-delete-modal", children: [jsx(DialogHeader, { children: jsx(DialogTitle, { className: "ibl-dialog-title", children: labels.deleteModal.title }) }), jsx("div", { className: "my-5", id: "tenant-cap-delete-description", children: jsx("p", { className: "text-sm text-[#646464]", children: labels.deleteModal.description }) }), jsxs(DialogFooter, { className: "gap-3", children: [jsx(Button$1, { variant: "outline", onClick: () => setIsDeleteOpen(false), children: labels.deleteModal.cancel }), jsx(Button$1, { className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", onClick: handleConfirmDelete, disabled: isDeletingTenantCap, "data-testid": "tenant-cap-delete-confirm", children: isDeletingTenantCap ? labels.form.removing : labels.deleteModal.confirm })] })] }) })] }));
|
|
194259
194972
|
}
|
|
194260
194973
|
|
|
194261
|
-
/** SPAs whose users have coursework, so the profile leads with a Gradebook tab. */
|
|
194262
|
-
const GRADEBOOK_SPAS = ['lms', 'skills'];
|
|
194263
|
-
/**
|
|
194264
|
-
* The customization `Profile` is opened with: whatever the host passed, with
|
|
194265
|
-
* the Gradebook tab defaulted from the SPA it runs in. An explicit
|
|
194266
|
-
* `showGradebookTab` always wins, so a host can force it either way.
|
|
194267
|
-
*/
|
|
194268
|
-
function profileCustomization(customization, currentSPA) {
|
|
194269
|
-
var _a;
|
|
194270
|
-
return {
|
|
194271
|
-
...customization,
|
|
194272
|
-
showGradebookTab: (_a = customization === null || customization === void 0 ? void 0 : customization.showGradebookTab) !== null && _a !== void 0 ? _a : GRADEBOOK_SPAS.includes((currentSPA !== null && currentSPA !== void 0 ? currentSPA : '').trim().toLowerCase()),
|
|
194273
|
-
};
|
|
194274
|
-
}
|
|
194275
|
-
/**
|
|
194276
|
-
* The shared `Profile` viewer in a dialog — the same modal the tenant
|
|
194277
|
-
* Management tab opens when a user row is clicked. Controlled variant for
|
|
194278
|
-
* hosts that trigger it from a whole table row.
|
|
194279
|
-
*
|
|
194280
|
-
* Radix portals the dialog into `document.body`, but a React portal still
|
|
194281
|
-
* bubbles its events through the React tree — so without the guard below, a
|
|
194282
|
-
* click *inside* the open profile would reach the row this dialog is rendered
|
|
194283
|
-
* from and fire its `onClick` (e.g. opening the enrollment progress modal
|
|
194284
|
-
* behind the profile). The wrapper is `display: contents`, so it adds nothing
|
|
194285
|
-
* to the host's layout.
|
|
194286
|
-
*/
|
|
194287
|
-
function UserProfileDialog({ tenantKey, username, isOpen, onClose, customization, currentSPA, }) {
|
|
194288
|
-
const t = useT();
|
|
194289
|
-
if (!isOpen)
|
|
194290
|
-
return null;
|
|
194291
|
-
return (jsx("span", { className: "contents", onClick: (event) => event.stopPropagation(), onMouseDown: (event) => event.stopPropagation(), onKeyDown: (event) => event.stopPropagation(), children: jsx(Dialog, { open: true, onOpenChange: onClose, children: jsxs(DialogContent, { autoFocus: false, className: "profile-component-dialog max-w-7xl w-[85vw] gap-0 overflow-hidden bg-white p-0", style: { height: '85vh', display: 'flex', flexDirection: 'column' }, "data-testid": "user-profile-link-dialog", children: [jsx(DialogTitle, { className: "sr-only", children: t('tabsUserstab.profileDialogTitle') }), jsx(DialogDescription, { className: "sr-only", children: t('tabsUserstab.profileDialogDescription') }), jsx(Profile, { tenant: tenantKey, tenants: [], username: username, onClose: onClose, customization: profileCustomization(customization, currentSPA), currentSPA: currentSPA })] }) }) }));
|
|
194292
|
-
}
|
|
194293
|
-
/**
|
|
194294
|
-
* Clickable user identity that opens the shared `Profile` viewer in a dialog
|
|
194295
|
-
* — the same modal the tenant Management tab opens when a user row is
|
|
194296
|
-
* clicked. `Profile` drops into preview (read-only) mode on its own for anyone
|
|
194297
|
-
* but the signed-in user. Used by the spend-cap tables and every analytics
|
|
194298
|
-
* surface that names a user; safe inside clickable rows and cards, since
|
|
194299
|
-
* neither its clicks nor its key presses reach the host's handlers.
|
|
194300
|
-
*/
|
|
194301
|
-
function UserProfileLink({ tenantKey, username, display, className, testId, customization, currentSPA, }) {
|
|
194302
|
-
const t = useT();
|
|
194303
|
-
const [isOpen, setIsOpen] = React__default.useState(false);
|
|
194304
|
-
if (!username) {
|
|
194305
|
-
// `inline-block`, or `truncate`'s `overflow: hidden` has nothing to clip:
|
|
194306
|
-
// an inline box takes its width from its own text.
|
|
194307
|
-
return (jsx("span", { className: cn('inline-block max-w-full truncate', className), "data-testid": testId, children: display }));
|
|
194308
|
-
}
|
|
194309
|
-
return (jsxs(Fragment$1, { children: [jsx("button", { type: "button", onClick: (event) => {
|
|
194310
|
-
event.stopPropagation();
|
|
194311
|
-
setIsOpen(true);
|
|
194312
|
-
},
|
|
194313
|
-
// Rows that open on Enter/Space would otherwise swallow the key press.
|
|
194314
|
-
onKeyDown: (event) => event.stopPropagation(), className: cn('max-w-full cursor-pointer truncate text-left hover:text-blue-600 hover:underline focus:text-blue-600 focus:outline-none', className), "aria-label": t('tabsUserstab.viewProfileAriaLabel', { name: display }), "data-testid": testId, children: display }), jsx(UserProfileDialog, { tenantKey: tenantKey, username: username, isOpen: isOpen, onClose: () => setIsOpen(false), customization: customization, currentSPA: currentSPA })] }));
|
|
194315
|
-
}
|
|
194316
|
-
|
|
194317
194974
|
/**
|
|
194318
194975
|
* Add/edit dialog for one per-user spend limit, mirroring the grader
|
|
194319
194976
|
* criterion modal: create mode starts with a searchable platform-user picker
|
|
@@ -214574,7 +215231,7 @@ function inputRulesPlugin(props) {
|
|
|
214574
215231
|
function getType(value) {
|
|
214575
215232
|
return Object.prototype.toString.call(value).slice(8, -1);
|
|
214576
215233
|
}
|
|
214577
|
-
function isPlainObject$
|
|
215234
|
+
function isPlainObject$2(value) {
|
|
214578
215235
|
if (getType(value) !== "Object") {
|
|
214579
215236
|
return false;
|
|
214580
215237
|
}
|
|
@@ -214584,9 +215241,9 @@ function isPlainObject$1(value) {
|
|
|
214584
215241
|
// src/utilities/mergeDeep.ts
|
|
214585
215242
|
function mergeDeep(target, source) {
|
|
214586
215243
|
const output = { ...target };
|
|
214587
|
-
if (isPlainObject$
|
|
215244
|
+
if (isPlainObject$2(target) && isPlainObject$2(source)) {
|
|
214588
215245
|
Object.keys(source).forEach((key) => {
|
|
214589
|
-
if (isPlainObject$
|
|
215246
|
+
if (isPlainObject$2(source[key]) && isPlainObject$2(target[key])) {
|
|
214590
215247
|
output[key] = mergeDeep(target[key], source[key]);
|
|
214591
215248
|
} else {
|
|
214592
215249
|
output[key] = source[key];
|
|
@@ -231411,6 +232068,501 @@ function TranscriptFiles({ files }) {
|
|
|
231411
232068
|
}) }));
|
|
231412
232069
|
}
|
|
231413
232070
|
|
|
232071
|
+
const asArray = (value) => (Array.isArray(value) ? value : []);
|
|
232072
|
+
const hasEntries = (value) => !!value && typeof value === 'object' && !Array.isArray(value) && Object.keys(value).length > 0;
|
|
232073
|
+
/** Rollup counts as the conversation-list endpoint reports them: numbers, numeric strings or `null`. */
|
|
232074
|
+
const toRollupCount = (value) => {
|
|
232075
|
+
const count = typeof value === 'string' ? Number(value) : (value !== null && value !== void 0 ? value : 0);
|
|
232076
|
+
return Number.isFinite(count) && count > 0 ? Math.floor(count) : 0;
|
|
232077
|
+
};
|
|
232078
|
+
/**
|
|
232079
|
+
* Sum the retrieved documents and tool calls over a conversation's turns, for
|
|
232080
|
+
* surfaces (the admin chat-history list) that carry the turns inline but have
|
|
232081
|
+
* no server-side rollup fields.
|
|
232082
|
+
*/
|
|
232083
|
+
function summarizeTranscriptTurns(turns) {
|
|
232084
|
+
return asArray(turns).reduce((rollup, turn) => ({
|
|
232085
|
+
documentsCount: rollup.documentsCount + asArray(turn === null || turn === void 0 ? void 0 : turn.documents).length,
|
|
232086
|
+
toolCallsCount: rollup.toolCallsCount + asArray(turn === null || turn === void 0 ? void 0 : turn.tool_calls).length,
|
|
232087
|
+
}), { documentsCount: 0, toolCallsCount: 0 });
|
|
232088
|
+
}
|
|
232089
|
+
/** A transcript's retrieved documents in the shape the chat's documents dialog lists. */
|
|
232090
|
+
function toRetrievedDocuments(documents) {
|
|
232091
|
+
return documents.map((doc) => {
|
|
232092
|
+
var _a, _b, _c, _d;
|
|
232093
|
+
return ({
|
|
232094
|
+
title: (_b = (_a = doc.title) !== null && _a !== void 0 ? _a : doc.source) !== null && _b !== void 0 ? _b : null,
|
|
232095
|
+
snippet: (_c = doc.snippet) !== null && _c !== void 0 ? _c : null,
|
|
232096
|
+
source: (_d = doc.source) !== null && _d !== void 0 ? _d : null,
|
|
232097
|
+
score: typeof doc.score === 'number' ? doc.score : null,
|
|
232098
|
+
});
|
|
232099
|
+
});
|
|
232100
|
+
}
|
|
232101
|
+
/**
|
|
232102
|
+
* Every document a conversation retrieved, across its turns, exactly as the
|
|
232103
|
+
* backend reports them — a source retrieved again on a later turn appears
|
|
232104
|
+
* again, so the count matches the backend's per-conversation totals. Comes
|
|
232105
|
+
* from the admin history payload itself, so it needs no per-user session
|
|
232106
|
+
* lookup.
|
|
232107
|
+
*/
|
|
232108
|
+
function conversationDocuments(turns) {
|
|
232109
|
+
return toRetrievedDocuments(asArray(turns).flatMap((turn) => asArray(turn === null || turn === void 0 ? void 0 : turn.documents)));
|
|
232110
|
+
}
|
|
232111
|
+
const asText = (value) => {
|
|
232112
|
+
if (value === null || value === undefined)
|
|
232113
|
+
return '';
|
|
232114
|
+
if (typeof value === 'string')
|
|
232115
|
+
return value;
|
|
232116
|
+
if (typeof value === 'number' || typeof value === 'boolean')
|
|
232117
|
+
return String(value);
|
|
232118
|
+
try {
|
|
232119
|
+
return JSON.stringify(value, null, 2);
|
|
232120
|
+
}
|
|
232121
|
+
catch (_a) {
|
|
232122
|
+
return String(value);
|
|
232123
|
+
}
|
|
232124
|
+
};
|
|
232125
|
+
/** A transcript's tool calls in the shape the chat's "Used N tools" record renders. */
|
|
232126
|
+
function toToolCallInfos(toolCalls) {
|
|
232127
|
+
return toolCalls.map((call, index) => {
|
|
232128
|
+
var _a;
|
|
232129
|
+
return ({
|
|
232130
|
+
id: `transcript-tool-${index}`,
|
|
232131
|
+
name: (_a = call.name) !== null && _a !== void 0 ? _a : '',
|
|
232132
|
+
input: call.input && typeof call.input === 'object' && !Array.isArray(call.input)
|
|
232133
|
+
? call.input
|
|
232134
|
+
: typeof call.input === 'string'
|
|
232135
|
+
? { input: call.input }
|
|
232136
|
+
: undefined,
|
|
232137
|
+
log: '',
|
|
232138
|
+
result: asText(call.output),
|
|
232139
|
+
});
|
|
232140
|
+
});
|
|
232141
|
+
}
|
|
232142
|
+
/** Whether a turn carries anything worth a details panel. */
|
|
232143
|
+
function hasTranscriptTurnDetails(turn) {
|
|
232144
|
+
if (!turn)
|
|
232145
|
+
return false;
|
|
232146
|
+
return (asArray(turn.documents).length > 0 ||
|
|
232147
|
+
asArray(turn.tool_calls).length > 0 ||
|
|
232148
|
+
hasEntries(turn.metadata) ||
|
|
232149
|
+
hasEntries(turn.request_context));
|
|
232150
|
+
}
|
|
232151
|
+
const isPlainObject$1 = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
|
|
232152
|
+
/** Nothing worth a row: null, blank strings, empty arrays and empty objects. */
|
|
232153
|
+
const isPresent = (value) => {
|
|
232154
|
+
if (value === null || value === undefined)
|
|
232155
|
+
return false;
|
|
232156
|
+
if (typeof value === 'string')
|
|
232157
|
+
return value.trim() !== '';
|
|
232158
|
+
if (Array.isArray(value))
|
|
232159
|
+
return value.length > 0;
|
|
232160
|
+
if (isPlainObject$1(value))
|
|
232161
|
+
return Object.keys(value).length > 0;
|
|
232162
|
+
return true;
|
|
232163
|
+
};
|
|
232164
|
+
const FIELD_ABBREVIATIONS$1 = new Set([
|
|
232165
|
+
'ai',
|
|
232166
|
+
'api',
|
|
232167
|
+
'css',
|
|
232168
|
+
'csv',
|
|
232169
|
+
'html',
|
|
232170
|
+
'http',
|
|
232171
|
+
'https',
|
|
232172
|
+
'id',
|
|
232173
|
+
'ids',
|
|
232174
|
+
'ip',
|
|
232175
|
+
'json',
|
|
232176
|
+
'llm',
|
|
232177
|
+
'lti',
|
|
232178
|
+
'mcp',
|
|
232179
|
+
'mime',
|
|
232180
|
+
'pdf',
|
|
232181
|
+
'rag',
|
|
232182
|
+
'sso',
|
|
232183
|
+
'stt',
|
|
232184
|
+
'tts',
|
|
232185
|
+
'ui',
|
|
232186
|
+
'uri',
|
|
232187
|
+
'url',
|
|
232188
|
+
'urls',
|
|
232189
|
+
'uuid',
|
|
232190
|
+
]);
|
|
232191
|
+
/**
|
|
232192
|
+
* "file_references" → "File References", "llmModel" → "LLM Model". Backend
|
|
232193
|
+
* keys are never shown raw: every unknown key goes through this, and the
|
|
232194
|
+
* common ones get a translated label on top (see `useFieldLabels`).
|
|
232195
|
+
*/
|
|
232196
|
+
function humanizeFieldName(key) {
|
|
232197
|
+
const words = key
|
|
232198
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
232199
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')
|
|
232200
|
+
.toLowerCase()
|
|
232201
|
+
.split(/[^a-z0-9]+/)
|
|
232202
|
+
.filter(Boolean);
|
|
232203
|
+
if (words.length === 0)
|
|
232204
|
+
return key;
|
|
232205
|
+
return words
|
|
232206
|
+
.map((word) => FIELD_ABBREVIATIONS$1.has(word)
|
|
232207
|
+
? word.toUpperCase()
|
|
232208
|
+
: word.charAt(0).toUpperCase() + word.slice(1))
|
|
232209
|
+
.join(' ');
|
|
232210
|
+
}
|
|
232211
|
+
/** Translated labels for the keys the backend is known to send. */
|
|
232212
|
+
function useFieldLabels() {
|
|
232213
|
+
const t = useT();
|
|
232214
|
+
const known = {
|
|
232215
|
+
llm_model: t('analyticsTranscriptTurnDetails.model'),
|
|
232216
|
+
llm_provider: t('analyticsTranscriptTurnDetails.provider'),
|
|
232217
|
+
llm_temperature: t('analyticsTranscriptTurnDetails.temperature'),
|
|
232218
|
+
model: t('analyticsTranscriptTurnDetails.model'),
|
|
232219
|
+
provider: t('analyticsTranscriptTurnDetails.provider'),
|
|
232220
|
+
temperature: t('analyticsTranscriptTurnDetails.temperature'),
|
|
232221
|
+
client: t('analyticsTranscriptTurnDetails.client'),
|
|
232222
|
+
session_id: t('analyticsTranscriptTurnDetails.fieldSession'),
|
|
232223
|
+
// The product's own names: artifacts are "Canvas" in the chat, proactivity
|
|
232224
|
+
// is the "Proactive Prompt", grading is the "Grader" tab, document filters
|
|
232225
|
+
// are "Datasets".
|
|
232226
|
+
enable_artifacts: t('analyticsTranscriptTurnDetails.fieldCanvas'),
|
|
232227
|
+
artifact: t('analyticsTranscriptTurnDetails.fieldCanvas'),
|
|
232228
|
+
artifacts: t('analyticsTranscriptTurnDetails.fieldCanvas'),
|
|
232229
|
+
is_proactive: t('analyticsTranscriptTurnDetails.fieldProactivePrompt'),
|
|
232230
|
+
grading_context: t('analyticsTranscriptTurnDetails.fieldGrader'),
|
|
232231
|
+
document_filter: t('analyticsTranscriptTurnDetails.fieldDatasets'),
|
|
232232
|
+
current_datetime: t('analyticsTranscriptTurnDetails.fieldDateTime'),
|
|
232233
|
+
caller_verified: t('analyticsTranscriptTurnDetails.fieldCallerVerified'),
|
|
232234
|
+
file_references: t('analyticsTranscriptTurnDetails.fieldFiles'),
|
|
232235
|
+
file_id: t('analyticsTranscriptTurnDetails.fieldFile'),
|
|
232236
|
+
system_prompt: t('analyticsTranscriptTurnDetails.fieldSystemPrompt'),
|
|
232237
|
+
flow: t('analyticsTranscriptTurnDetails.fieldFlow'),
|
|
232238
|
+
token: t('analyticsTranscriptTurnDetails.fieldToken'),
|
|
232239
|
+
tenant: t('analyticsTranscriptTurnDetails.fieldTenant'),
|
|
232240
|
+
pathway: t('analyticsTranscriptTurnDetails.fieldPathway'),
|
|
232241
|
+
username: t('analyticsTranscriptTurnDetails.fieldUsername'),
|
|
232242
|
+
name: t('analyticsTranscriptTurnDetails.fieldName'),
|
|
232243
|
+
};
|
|
232244
|
+
return (key) => { var _a; return (_a = known[key]) !== null && _a !== void 0 ? _a : humanizeFieldName(key); };
|
|
232245
|
+
}
|
|
232246
|
+
const fileName = (value) => {
|
|
232247
|
+
var _a, _b, _c, _d;
|
|
232248
|
+
const name = (_b = (_a = value.file_name) !== null && _a !== void 0 ? _a : value.filename) !== null && _b !== void 0 ? _b : value.name;
|
|
232249
|
+
if (typeof name === 'string' && name.trim())
|
|
232250
|
+
return name.trim();
|
|
232251
|
+
const key = (_d = (_c = value.file_key) !== null && _c !== void 0 ? _c : value.key) !== null && _d !== void 0 ? _d : value.path;
|
|
232252
|
+
if (typeof key === 'string' && key.trim())
|
|
232253
|
+
return key.trim().split('/').pop() || key.trim();
|
|
232254
|
+
return undefined;
|
|
232255
|
+
};
|
|
232256
|
+
/** Backend payloads name files in a few shapes; anything with a name plus a file-ish fact counts. */
|
|
232257
|
+
function isFileReference(value) {
|
|
232258
|
+
if (!isPlainObject$1(value) || !fileName(value))
|
|
232259
|
+
return false;
|
|
232260
|
+
return ['file_id', 'file_key', 'file_size', 'content_type', 'mime_type', 'url', 'size'].some((key) => key in value && value[key] !== null && value[key] !== undefined);
|
|
232261
|
+
}
|
|
232262
|
+
const attachmentUrl = (name, attachments) => { var _a; return (_a = attachments === null || attachments === void 0 ? void 0 : attachments.find((file) => (file === null || file === void 0 ? void 0 : file.name) === name && !!file.url)) === null || _a === void 0 ? void 0 : _a.url; };
|
|
232263
|
+
/** Normalise a file reference; the turn's attachments lend their presigned `url` to a same-named file. */
|
|
232264
|
+
function toFileReference(value, attachments) {
|
|
232265
|
+
var _a, _b, _c, _d, _e, _f;
|
|
232266
|
+
const name = (_a = fileName(value)) !== null && _a !== void 0 ? _a : '';
|
|
232267
|
+
const contentType = (_c = (_b = value.content_type) !== null && _b !== void 0 ? _b : value.mime_type) !== null && _c !== void 0 ? _c : value.type;
|
|
232268
|
+
const size = (_d = value.file_size) !== null && _d !== void 0 ? _d : value.size;
|
|
232269
|
+
const own = (_f = (_e = value.url) !== null && _e !== void 0 ? _e : value.download_url) !== null && _f !== void 0 ? _f : value.href;
|
|
232270
|
+
const numericSize = typeof size === 'number'
|
|
232271
|
+
? size
|
|
232272
|
+
: typeof size === 'string' && size.trim() && Number.isFinite(Number(size))
|
|
232273
|
+
? Number(size)
|
|
232274
|
+
: undefined;
|
|
232275
|
+
return {
|
|
232276
|
+
name,
|
|
232277
|
+
contentType: typeof contentType === 'string' ? contentType : undefined,
|
|
232278
|
+
size: numericSize,
|
|
232279
|
+
url: typeof own === 'string' && own ? own : attachmentUrl(name, attachments),
|
|
232280
|
+
};
|
|
232281
|
+
}
|
|
232282
|
+
const formatFileSize = (bytes) => {
|
|
232283
|
+
if (bytes === undefined || !Number.isFinite(bytes) || bytes < 0)
|
|
232284
|
+
return '';
|
|
232285
|
+
if (bytes < 1024)
|
|
232286
|
+
return `${bytes} B`;
|
|
232287
|
+
if (bytes < 1024 * 1024)
|
|
232288
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
232289
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
232290
|
+
};
|
|
232291
|
+
const REDACTED_PATTERN = /^\[?(redacted|hidden|masked|removed)\]?$|^\*{3,}$/i;
|
|
232292
|
+
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
232293
|
+
/** Past this depth nested objects flatten to "key: value" text rather than nesting further. */
|
|
232294
|
+
const MAX_NESTING = 4;
|
|
232295
|
+
const formatPrimitive = (value) => {
|
|
232296
|
+
if (value === null || value === undefined)
|
|
232297
|
+
return '';
|
|
232298
|
+
if (typeof value === 'string')
|
|
232299
|
+
return value;
|
|
232300
|
+
if (typeof value === 'number')
|
|
232301
|
+
return Number.isInteger(value) ? String(value) : String(value);
|
|
232302
|
+
return String(value);
|
|
232303
|
+
};
|
|
232304
|
+
/** Deeply nested leftovers as readable "Key: value" text — never JSON. */
|
|
232305
|
+
function compactText(value, labelFor) {
|
|
232306
|
+
if (Array.isArray(value)) {
|
|
232307
|
+
return value
|
|
232308
|
+
.filter(isPresent)
|
|
232309
|
+
.map((item) => compactText(item, labelFor))
|
|
232310
|
+
.join('; ');
|
|
232311
|
+
}
|
|
232312
|
+
if (isPlainObject$1(value)) {
|
|
232313
|
+
return Object.entries(value)
|
|
232314
|
+
.filter(([, v]) => isPresent(v))
|
|
232315
|
+
.map(([k, v]) => `${labelFor(k)}: ${compactText(v, labelFor)}`)
|
|
232316
|
+
.join(', ');
|
|
232317
|
+
}
|
|
232318
|
+
return formatPrimitive(value);
|
|
232319
|
+
}
|
|
232320
|
+
function BooleanValue({ value }) {
|
|
232321
|
+
const t = useT();
|
|
232322
|
+
return (jsx("span", { className: cn('inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium', value ? 'bg-green-50 text-green-700' : 'bg-gray-100 text-gray-600'), children: value ? t('analyticsTranscriptTurnDetails.yes') : t('analyticsTranscriptTurnDetails.no') }));
|
|
232323
|
+
}
|
|
232324
|
+
function StringValue({ value }) {
|
|
232325
|
+
const t = useT();
|
|
232326
|
+
const text = value.trim();
|
|
232327
|
+
if (REDACTED_PATTERN.test(text)) {
|
|
232328
|
+
return (jsx("span", { className: "text-gray-400 italic", children: t('analyticsTranscriptTurnDetails.redacted') }));
|
|
232329
|
+
}
|
|
232330
|
+
if (UUID_PATTERN.test(text)) {
|
|
232331
|
+
return jsx("span", { className: "font-mono text-xs break-all text-gray-700", children: text });
|
|
232332
|
+
}
|
|
232333
|
+
return (jsx("span", { className: "block max-h-48 overflow-y-auto break-words whitespace-pre-line", children: text }));
|
|
232334
|
+
}
|
|
232335
|
+
const DetailCtx = React__default.createContext({ labelFor: humanizeFieldName });
|
|
232336
|
+
function DetailValue({ value, depth, labelFor, }) {
|
|
232337
|
+
var _a, _b;
|
|
232338
|
+
const ctx = React__default.useContext(DetailCtx);
|
|
232339
|
+
if (typeof value === 'boolean')
|
|
232340
|
+
return jsx(BooleanValue, { value: value });
|
|
232341
|
+
if (typeof value === 'number')
|
|
232342
|
+
return jsx("span", { className: "tabular-nums", children: formatPrimitive(value) });
|
|
232343
|
+
if (typeof value === 'string')
|
|
232344
|
+
return jsx(StringValue, { value: value });
|
|
232345
|
+
if (depth >= MAX_NESTING) {
|
|
232346
|
+
return jsx("span", { className: "break-words", children: compactText(value, labelFor) });
|
|
232347
|
+
}
|
|
232348
|
+
if (isFileReference(value)) {
|
|
232349
|
+
const files = [toFileReference(value, ctx.attachments)];
|
|
232350
|
+
return jsx(Fragment$1, { children: ((_a = ctx.renderFiles) !== null && _a !== void 0 ? _a : defaultRenderFiles)(files) });
|
|
232351
|
+
}
|
|
232352
|
+
if (Array.isArray(value)) {
|
|
232353
|
+
const items = value.filter(isPresent);
|
|
232354
|
+
if (items.length === 0)
|
|
232355
|
+
return null;
|
|
232356
|
+
if (items.every(isFileReference)) {
|
|
232357
|
+
const files = items.map((item) => toFileReference(item, ctx.attachments));
|
|
232358
|
+
return jsx(Fragment$1, { children: ((_b = ctx.renderFiles) !== null && _b !== void 0 ? _b : defaultRenderFiles)(files) });
|
|
232359
|
+
}
|
|
232360
|
+
const allPrimitive = items.every((item) => !isPlainObject$1(item) && !Array.isArray(item));
|
|
232361
|
+
if (allPrimitive) {
|
|
232362
|
+
return (jsx("span", { className: "flex flex-wrap gap-1", children: items.map((item, index) => (jsx(Badge, { variant: "secondary", className: "max-w-full font-normal break-all whitespace-normal", children: typeof item === 'boolean' ? jsx(BooleanValue, { value: item }) : formatPrimitive(item) }, index))) }));
|
|
232363
|
+
}
|
|
232364
|
+
return (jsx("ol", { className: "space-y-2", children: items.map((item, index) => (jsxs("li", { className: "flex gap-2", children: [jsxs("span", { className: "mt-1 text-xs font-medium text-gray-400 tabular-nums", children: [index + 1, "."] }), jsx("div", { className: "min-w-0 flex-1 rounded-md border border-gray-200 px-3 py-1", children: isPlainObject$1(item) ? (jsx(DetailRows, { entries: item, depth: depth + 1, labelFor: labelFor })) : (jsx(DetailValue, { value: item, depth: depth + 1, labelFor: labelFor })) })] }, index))) }));
|
|
232365
|
+
}
|
|
232366
|
+
if (isPlainObject$1(value)) {
|
|
232367
|
+
return (jsx("div", { className: "border-l-2 border-gray-200 pl-3", children: jsx(DetailRows, { entries: value, depth: depth + 1, labelFor: labelFor }) }));
|
|
232368
|
+
}
|
|
232369
|
+
return jsx("span", { children: formatPrimitive(value) });
|
|
232370
|
+
}
|
|
232371
|
+
/**
|
|
232372
|
+
* Label/value rows for a metadata-style object. Keys are humanized (never
|
|
232373
|
+
* shown raw), blanks are skipped, booleans read Yes/No, lists become chips or
|
|
232374
|
+
* numbered cards, files become the chat's file cards and nested objects
|
|
232375
|
+
* indent — the same read-only detail style as the audit-log sheet, so nothing
|
|
232376
|
+
* here ever looks like a JSON dump.
|
|
232377
|
+
*/
|
|
232378
|
+
function DetailRows({ entries, depth = 0, labelFor, }) {
|
|
232379
|
+
const rows = Object.entries(entries).filter(([, value]) => isPresent(value));
|
|
232380
|
+
if (rows.length === 0)
|
|
232381
|
+
return null;
|
|
232382
|
+
const top = depth === 0;
|
|
232383
|
+
return (jsx("dl", { className: cn(top ? 'divide-y divide-gray-100' : 'space-y-1'), children: rows.map(([key, value]) => (jsxs("div", { className: cn('grid gap-x-3', top
|
|
232384
|
+
? 'grid-cols-[minmax(0,7rem)_minmax(0,1fr)] py-2'
|
|
232385
|
+
: 'grid-cols-[minmax(0,6rem)_minmax(0,1fr)] py-0.5'), children: [jsx("dt", { className: cn('break-words text-gray-500', top ? 'text-xs font-medium tracking-wide uppercase' : 'text-xs font-medium'), children: labelFor(key) }), jsx("dd", { className: "min-w-0 text-sm text-gray-800", children: jsx(DetailValue, { value: value, depth: depth, labelFor: labelFor }) })] }, key))) }));
|
|
232386
|
+
}
|
|
232387
|
+
function SectionHeading({ icon, children }) {
|
|
232388
|
+
return (jsxs("h4", { className: "mb-2 flex items-center gap-1.5 text-xs font-semibold tracking-wide text-gray-700 uppercase", children: [icon, children] }));
|
|
232389
|
+
}
|
|
232390
|
+
const MODEL_KEYS = new Set(['llm_model', 'llm_provider']);
|
|
232391
|
+
function MetadataSection({ metadata, renderModel, }) {
|
|
232392
|
+
var _a, _b;
|
|
232393
|
+
const t = useT();
|
|
232394
|
+
const labelFor = useFieldLabels();
|
|
232395
|
+
const rest = Object.fromEntries(Object.entries(metadata).filter(([key]) => !MODEL_KEYS.has(key)));
|
|
232396
|
+
const model = ((_a = metadata.llm_model) !== null && _a !== void 0 ? _a : '').trim() || undefined;
|
|
232397
|
+
const provider = ((_b = metadata.llm_provider) !== null && _b !== void 0 ? _b : '').trim() || undefined;
|
|
232398
|
+
const hasModel = !!(model || provider);
|
|
232399
|
+
return (jsxs("section", { "data-testid": "transcript-turn-metadata", children: [jsx(SectionHeading, { icon: jsx(Info$3, { className: "h-3.5 w-3.5", "aria-hidden": "true" }), children: t('analyticsTranscriptTurnDetails.metadata') }), hasModel && (jsx("div", { "data-testid": "transcript-turn-model", className: "mb-2", children: (renderModel !== null && renderModel !== void 0 ? renderModel : defaultRenderModel)({ model, provider }) })), jsx(DetailRows, { entries: rest, labelFor: labelFor })] }));
|
|
232400
|
+
}
|
|
232401
|
+
function RequestContextSection({ requestContext }) {
|
|
232402
|
+
const t = useT();
|
|
232403
|
+
const labelFor = useFieldLabels();
|
|
232404
|
+
return (jsxs("section", { "data-testid": "transcript-turn-request-context", children: [jsx(SectionHeading, { icon: jsx(Info$3, { className: "h-3.5 w-3.5", "aria-hidden": "true" }), children: t('analyticsTranscriptTurnDetails.requestContext') }), jsx(DetailRows, { entries: requestContext, labelFor: labelFor })] }));
|
|
232405
|
+
}
|
|
232406
|
+
/**
|
|
232407
|
+
* The panel's defaults are the chat's own components, so admins see exactly
|
|
232408
|
+
* what the conversation shows: the "Retrieved Documents" dialog button, the
|
|
232409
|
+
* "Used N tools" record (with results), the nav-bar model badge and the
|
|
232410
|
+
* attachment file cards.
|
|
232411
|
+
*/
|
|
232412
|
+
const defaultRenderDocuments = (documents) => (jsx(RetrievedDocumentsButton, { documents: toRetrievedDocuments(documents) }));
|
|
232413
|
+
const defaultRenderToolCalls = (toolCalls) => (jsx(ToolCallIndicator, { toolCalls: toToolCallInfos(toolCalls), showResults: true }));
|
|
232414
|
+
const defaultRenderModel = ({ model, provider }) => (jsx(LlmModelBadge, { model: model, provider: provider }));
|
|
232415
|
+
const defaultRenderFiles = (files) => (jsx(TranscriptFileCards, { files: files }));
|
|
232416
|
+
/**
|
|
232417
|
+
* Collapsible "Sources / Tools / Metadata" panel for one AI turn of an admin
|
|
232418
|
+
* transcript (Perplexity/Claude-style citations). Driven by the extended
|
|
232419
|
+
* per-turn context the backend attaches on admin surfaces — the analytics
|
|
232420
|
+
* `messages/details/` endpoint and the admin `chat-history/` list — and
|
|
232421
|
+
* renders nothing at all when every field is null or empty, so it is safe to
|
|
232422
|
+
* drop under every AI bubble.
|
|
232423
|
+
*/
|
|
232424
|
+
function TranscriptTurnDetails({ turn, className, defaultOpen = false, renderDocuments, renderToolCalls, renderModel, renderFiles, }) {
|
|
232425
|
+
const t = useT();
|
|
232426
|
+
const labelFor = useFieldLabels();
|
|
232427
|
+
const [open, setOpen] = React__default.useState(defaultOpen);
|
|
232428
|
+
const attachments = React__default.useMemo(() => [...asArray(turn === null || turn === void 0 ? void 0 : turn.human_files), ...asArray(turn === null || turn === void 0 ? void 0 : turn.ai_files)], [turn === null || turn === void 0 ? void 0 : turn.human_files, turn === null || turn === void 0 ? void 0 : turn.ai_files]);
|
|
232429
|
+
const detailContext = React__default.useMemo(() => ({ labelFor, attachments, renderFiles }), [labelFor, attachments, renderFiles]);
|
|
232430
|
+
if (!hasTranscriptTurnDetails(turn))
|
|
232431
|
+
return null;
|
|
232432
|
+
const documents = asArray(turn === null || turn === void 0 ? void 0 : turn.documents);
|
|
232433
|
+
const toolCalls = asArray(turn === null || turn === void 0 ? void 0 : turn.tool_calls);
|
|
232434
|
+
const metadata = hasEntries(turn === null || turn === void 0 ? void 0 : turn.metadata) ? turn === null || turn === void 0 ? void 0 : turn.metadata : null;
|
|
232435
|
+
const requestContext = hasEntries(turn === null || turn === void 0 ? void 0 : turn.request_context) ? turn === null || turn === void 0 ? void 0 : turn.request_context : null;
|
|
232436
|
+
return (jsx(DetailCtx.Provider, { value: detailContext, children: jsxs(Collapsible, { open: open, onOpenChange: setOpen, className: cn('mt-2', className), "data-testid": "transcript-turn-details", children: [jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [jsx(CollapsibleTrigger, { asChild: true, children: jsxs(Button$1, { type: "button", variant: "outline", size: "sm", className: "flex items-center gap-2 border-gray-200 bg-white text-gray-700 hover:bg-gray-50", "aria-expanded": open, children: [jsx(ChevronDown, { className: cn('h-4 w-4 transition-transform', open && 'rotate-180'), "aria-hidden": "true" }), open
|
|
232437
|
+
? t('analyticsTranscriptTurnDetails.hideDetails')
|
|
232438
|
+
: t('analyticsTranscriptTurnDetails.showDetails')] }) }), documents.length > 0 && (jsx("div", { "data-testid": "transcript-turn-sources", className: "contents", children: (renderDocuments !== null && renderDocuments !== void 0 ? renderDocuments : defaultRenderDocuments)(documents) })), jsx(TranscriptRollupBadges, { documentsCount: 0, toolCallsCount: toolCalls.length })] }), jsxs(CollapsibleContent, { className: "mt-2 space-y-5 rounded-lg border border-gray-200 bg-white p-3", children: [toolCalls.length > 0 && (jsx("div", { "data-testid": "transcript-turn-tools", children: (renderToolCalls !== null && renderToolCalls !== void 0 ? renderToolCalls : defaultRenderToolCalls)(toolCalls) })), metadata && jsx(MetadataSection, { metadata: metadata, renderModel: renderModel }), requestContext && jsx(RequestContextSection, { requestContext: requestContext })] })] }) }));
|
|
232439
|
+
}
|
|
232440
|
+
/**
|
|
232441
|
+
* "Documents · N" / "Tools · N" chips for a conversation row, from the
|
|
232442
|
+
* conversation-list rollup fields (or a client-side `summarizeTranscriptTurns`).
|
|
232443
|
+
* A chip is hidden when its count is zero; nothing renders when both are.
|
|
232444
|
+
*/
|
|
232445
|
+
function TranscriptRollupBadges({ documentsCount, toolCallsCount, className, }) {
|
|
232446
|
+
const t = useT();
|
|
232447
|
+
const documents = toRollupCount(documentsCount);
|
|
232448
|
+
const tools = toRollupCount(toolCallsCount);
|
|
232449
|
+
if (documents === 0 && tools === 0)
|
|
232450
|
+
return null;
|
|
232451
|
+
return (jsxs("span", { className: cn('inline-flex flex-wrap items-center gap-1.5', className), "data-testid": "transcript-rollup-badges", children: [documents > 0 && (jsxs(Badge, { variant: "outline", className: "gap-1 border-transparent bg-blue-50 font-normal text-blue-700", "data-testid": "transcript-sources-badge", children: [jsx(FileText, { className: "h-3 w-3", "aria-hidden": "true" }), t('analyticsTranscriptTurnDetails.sourcesBadge', { count: documents })] })), tools > 0 && (jsxs(Badge, { variant: "outline", className: "gap-1 border-transparent bg-amber-50 font-normal text-amber-800", "data-testid": "transcript-tools-badge", children: [jsx(Wrench, { className: "h-3 w-3", "aria-hidden": "true" }), t('analyticsTranscriptTurnDetails.toolsBadge', { count: tools })] }))] }));
|
|
232452
|
+
}
|
|
232453
|
+
|
|
232454
|
+
/**
|
|
232455
|
+
* One place that decides how a user is shown.
|
|
232456
|
+
*
|
|
232457
|
+
* Backend payloads name their user in a dozen ways — `email` / `lti_email` /
|
|
232458
|
+
* `user_email`, `username` / `student` / `lti_username`, `name` /
|
|
232459
|
+
* `full_name` / `user_full_name`, or a nested `user` object — and most of
|
|
232460
|
+
* them can be empty, `null`, or a placeholder like "None". Every surface used
|
|
232461
|
+
* to pick through those on its own. `resolveUserIdentity()` takes whatever
|
|
232462
|
+
* the payload is and returns what to show, what to open a profile on, and
|
|
232463
|
+
* the avatar initial, so the rule lives here and can be tweaked once.
|
|
232464
|
+
*
|
|
232465
|
+
* Default rule: email → full name → username → the anonymous label.
|
|
232466
|
+
*/
|
|
232467
|
+
const DEFAULT_USER_IDENTITY_ORDER = ['email', 'name', 'username'];
|
|
232468
|
+
const DEFAULT_ANONYMOUS_LABEL = 'Anonymous';
|
|
232469
|
+
/** Values backends emit instead of "nothing". Compared case-insensitively. */
|
|
232470
|
+
const PLACEHOLDERS = new Set([
|
|
232471
|
+
'',
|
|
232472
|
+
'none',
|
|
232473
|
+
'null',
|
|
232474
|
+
'undefined',
|
|
232475
|
+
'n/a',
|
|
232476
|
+
'na',
|
|
232477
|
+
'-',
|
|
232478
|
+
'anonymous',
|
|
232479
|
+
'anonymoususer',
|
|
232480
|
+
]);
|
|
232481
|
+
/**
|
|
232482
|
+
* `local@domain.tld` with no whitespace, checked with a single pass rather than
|
|
232483
|
+
* a backtracking pattern (CodeQL flags `[^@]+@[^@]+\.[^@]+` as polynomial on
|
|
232484
|
+
* adversarial input).
|
|
232485
|
+
*/
|
|
232486
|
+
const isEmailLike = (value) => {
|
|
232487
|
+
const text = value.trim();
|
|
232488
|
+
if (!text || /\s/.test(text))
|
|
232489
|
+
return false;
|
|
232490
|
+
const at = text.indexOf('@');
|
|
232491
|
+
if (at <= 0 || at !== text.lastIndexOf('@') || at === text.length - 1)
|
|
232492
|
+
return false;
|
|
232493
|
+
const domain = text.slice(at + 1);
|
|
232494
|
+
const dot = domain.indexOf('.');
|
|
232495
|
+
// A dot somewhere inside the domain, with something after the last one.
|
|
232496
|
+
return dot > 0 && !domain.endsWith('.');
|
|
232497
|
+
};
|
|
232498
|
+
/** Trimmed string, or undefined for blanks, non-strings and placeholders. */
|
|
232499
|
+
const clean = (value) => {
|
|
232500
|
+
if (typeof value !== 'string')
|
|
232501
|
+
return undefined;
|
|
232502
|
+
const trimmed = value.trim();
|
|
232503
|
+
return PLACEHOLDERS.has(trimmed.toLowerCase()) ? undefined : trimmed;
|
|
232504
|
+
};
|
|
232505
|
+
const firstOf = (...candidates) => {
|
|
232506
|
+
for (const candidate of candidates) {
|
|
232507
|
+
const value = clean(candidate);
|
|
232508
|
+
if (value)
|
|
232509
|
+
return value;
|
|
232510
|
+
}
|
|
232511
|
+
return undefined;
|
|
232512
|
+
};
|
|
232513
|
+
const nested = (source) => source.user && typeof source.user === 'object' ? source.user : undefined;
|
|
232514
|
+
/**
|
|
232515
|
+
* Resolve how a user should be displayed from any payload that names one.
|
|
232516
|
+
*
|
|
232517
|
+
* - `email`: `lti_email`, `email`, `user_email`, the nested `user`'s email —
|
|
232518
|
+
* or a username field that turns out to hold an email address.
|
|
232519
|
+
* - `username`: `lti_username`, `username`, `student`, `user_username`, the
|
|
232520
|
+
* nested `user`'s username, or a bare string/number `user` value.
|
|
232521
|
+
* - `name`: `user_full_name`, `full_name`, `name`, `first_name last_name`, or
|
|
232522
|
+
* the nested `user`'s name.
|
|
232523
|
+
* - `profileUsername`: the first *platform* username (never an LTI claim).
|
|
232524
|
+
*
|
|
232525
|
+
* A string source is treated as an email when it looks like one, else as a
|
|
232526
|
+
* username. Placeholder strings ("None", "-", "anonymous"…) count as absent.
|
|
232527
|
+
*/
|
|
232528
|
+
function resolveUserIdentity(source, options = {}) {
|
|
232529
|
+
var _a;
|
|
232530
|
+
const anonymousLabel = options.anonymousLabel || DEFAULT_ANONYMOUS_LABEL;
|
|
232531
|
+
const order = ((_a = options.order) === null || _a === void 0 ? void 0 : _a.length) ? options.order : DEFAULT_USER_IDENTITY_ORDER;
|
|
232532
|
+
const record = source && typeof source === 'object' ? source : { user: source !== null && source !== void 0 ? source : null };
|
|
232533
|
+
const inner = nested(record);
|
|
232534
|
+
// A bare `user` value is an id or username; numeric ids are still shown.
|
|
232535
|
+
const bareUser = typeof record.user === 'number' && Number.isFinite(record.user)
|
|
232536
|
+
? String(record.user)
|
|
232537
|
+
: typeof record.user === 'string'
|
|
232538
|
+
? clean(record.user)
|
|
232539
|
+
: undefined;
|
|
232540
|
+
let email = firstOf(record.lti_email, record.email, record.user_email, inner === null || inner === void 0 ? void 0 : inner.lti_email, inner === null || inner === void 0 ? void 0 : inner.email, inner === null || inner === void 0 ? void 0 : inner.user_email);
|
|
232541
|
+
const platformUsername = firstOf(record.username, record.student, record.user_username, inner === null || inner === void 0 ? void 0 : inner.username, inner === null || inner === void 0 ? void 0 : inner.student, inner === null || inner === void 0 ? void 0 : inner.user_username, bareUser && !isEmailLike(bareUser) ? bareUser : undefined);
|
|
232542
|
+
let username = firstOf(record.lti_username, inner === null || inner === void 0 ? void 0 : inner.lti_username, platformUsername);
|
|
232543
|
+
const composed = [clean(record.first_name), clean(record.last_name)].filter(Boolean).join(' ');
|
|
232544
|
+
const name = firstOf(record.user_full_name, record.full_name, record.name, composed, inner === null || inner === void 0 ? void 0 : inner.user_full_name, inner === null || inner === void 0 ? void 0 : inner.full_name, inner === null || inner === void 0 ? void 0 : inner.name);
|
|
232545
|
+
// A bare string that looks like an email is an email, and so is a
|
|
232546
|
+
// "username" field that actually carries one.
|
|
232547
|
+
if (!email && bareUser && isEmailLike(bareUser))
|
|
232548
|
+
email = bareUser;
|
|
232549
|
+
if (!email && username && isEmailLike(username)) {
|
|
232550
|
+
email = username;
|
|
232551
|
+
username = undefined;
|
|
232552
|
+
}
|
|
232553
|
+
const facts = { email, username, name };
|
|
232554
|
+
const label = order.map((field) => facts[field]).find(Boolean);
|
|
232555
|
+
return {
|
|
232556
|
+
label: label !== null && label !== void 0 ? label : anonymousLabel,
|
|
232557
|
+
email,
|
|
232558
|
+
username,
|
|
232559
|
+
name,
|
|
232560
|
+
profileUsername: platformUsername,
|
|
232561
|
+
initial: (label !== null && label !== void 0 ? label : anonymousLabel).charAt(0).toUpperCase() || 'A',
|
|
232562
|
+
isAnonymous: !label,
|
|
232563
|
+
};
|
|
232564
|
+
}
|
|
232565
|
+
|
|
231414
232566
|
// Utility function to format relative time
|
|
231415
232567
|
const formatRelativeTime = (dateString, t) => {
|
|
231416
232568
|
const date = new Date(dateString);
|
|
@@ -231450,13 +232602,50 @@ const getMessageContent = (content) => {
|
|
|
231450
232602
|
return '';
|
|
231451
232603
|
};
|
|
231452
232604
|
/**
|
|
231453
|
-
* Label for whoever a transcript belongs to
|
|
231454
|
-
* email only on newer deployments, so it
|
|
231455
|
-
* name / username stand in behind it
|
|
232605
|
+
* Label for whoever a transcript belongs to, via the shared identity rule.
|
|
232606
|
+
* The analytics payload carries an email only on newer deployments, so it
|
|
232607
|
+
* wins where present and the display name / username stand in behind it,
|
|
232608
|
+
* in the order the caller asks for; "-" when the row names nobody.
|
|
231456
232609
|
*/
|
|
231457
|
-
const identifyUser = (
|
|
231458
|
-
|
|
231459
|
-
|
|
232610
|
+
const identifyUser = (source, order) => resolveUserIdentity(source, { order, anonymousLabel: '-' }).label;
|
|
232611
|
+
/** The model as the nav bar shows it (logo + display name); hosts may override via `turnDetails.renderModel`. */
|
|
232612
|
+
const renderModelBadge = ({ model, provider }) => (jsx(LlmModelBadge, { model: model, provider: provider }));
|
|
232613
|
+
/** Newer deployments name the provider on rows and summaries; older ones only the model. */
|
|
232614
|
+
const providerOf = (source) => {
|
|
232615
|
+
const value = source === null || source === void 0 ? void 0 : source.llm_provider;
|
|
232616
|
+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
232617
|
+
};
|
|
232618
|
+
/**
|
|
232619
|
+
* The provider the transcript's turns ran on — the same `metadata.llm_provider`
|
|
232620
|
+
* the per-turn details show — so the header badge resolves its logo exactly
|
|
232621
|
+
* like the metadata badge does, whatever spelling the summary's `model` uses.
|
|
232622
|
+
*/
|
|
232623
|
+
const providerOfTurns = (messages) => {
|
|
232624
|
+
var _a;
|
|
232625
|
+
if (!Array.isArray(messages))
|
|
232626
|
+
return undefined;
|
|
232627
|
+
for (const message of messages) {
|
|
232628
|
+
const provider = (_a = message === null || message === void 0 ? void 0 : message.metadata) === null || _a === void 0 ? void 0 : _a.llm_provider;
|
|
232629
|
+
if (typeof provider === 'string' && provider.trim())
|
|
232630
|
+
return provider.trim();
|
|
232631
|
+
}
|
|
232632
|
+
return undefined;
|
|
232633
|
+
};
|
|
232634
|
+
/**
|
|
232635
|
+
* Everything the transcript retrieved, as the chat offers it — from the
|
|
232636
|
+
* detail turns when they carry documents, else the session's own lookup.
|
|
232637
|
+
*/
|
|
232638
|
+
function TranscriptDocumentsButton({ detail, className, }) {
|
|
232639
|
+
var _a;
|
|
232640
|
+
const turns = Array.isArray(detail === null || detail === void 0 ? void 0 : detail.messages) ? detail === null || detail === void 0 ? void 0 : detail.messages : [];
|
|
232641
|
+
const documents = conversationDocuments(turns);
|
|
232642
|
+
const sessionId = ((_a = detail === null || detail === void 0 ? void 0 : detail.summary) === null || _a === void 0 ? void 0 : _a.session) ? String(detail.summary.session) : '';
|
|
232643
|
+
if (documents.length === 0 && !sessionId)
|
|
232644
|
+
return null;
|
|
232645
|
+
return (jsx(RetrievedDocumentsButton, { sessionId: sessionId, documents: documents.length > 0 ? documents : undefined, className: className }));
|
|
232646
|
+
}
|
|
232647
|
+
function AnalyticsTranscriptsStats({ tenantKey, currentSPA, mentorId, selectedMentorId, usergroupIds, turnDetails, }) {
|
|
232648
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
231460
232649
|
const t = useT();
|
|
231461
232650
|
const currentMentorId = useScopedMentorId(selectedMentorId, mentorId);
|
|
231462
232651
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
@@ -231565,16 +232754,21 @@ function AnalyticsTranscriptsStats({ tenantKey, currentSPA, mentorId, selectedMe
|
|
|
231565
232754
|
};
|
|
231566
232755
|
// Transcript Detail Component (reusable for both desktop and mobile)
|
|
231567
232756
|
const TranscriptDetail = ({ className = '' }) => {
|
|
231568
|
-
var _a, _b, _c, _d, _e, _f, _g, _h
|
|
232757
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
231569
232758
|
return (jsx("div", { className: cn('h-full flex flex-col', className), children: !selectedTranscript ? (jsx("div", { className: "flex items-center justify-center h-full text-gray-400", children: jsxs("div", { className: "text-center", children: [jsx(ArrowLeft, { className: "h-6 w-6 mx-auto mb-2" }), jsx("p", { children: t('analyticsAnalyticsTranscriptsStats.selectConversation') })] }) })) : isLoadingTranscriptsMessagesDetailsData ? (
|
|
231570
232759
|
/* Loading state */
|
|
231571
232760
|
jsx("div", { className: "flex items-center justify-center h-full text-gray-400", children: jsxs("div", { className: "text-center", children: [jsx("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500 mx-auto mb-3", "aria-hidden": "true" }), jsx("p", { children: t('analyticsAnalyticsTranscriptsStats.loadingTranscript') })] }) })) : isErrorTranscriptsMessagesDetailsData || !transcriptsMessagesDetailsData ? (
|
|
231572
232761
|
/* Error or no data state */
|
|
231573
232762
|
jsx("div", { className: "flex items-center justify-center h-full text-gray-400", children: jsxs("div", { className: "text-center", children: [jsx(X$1, { className: "h-6 w-6 mx-auto mb-2 text-red-400" }), jsx("p", { children: t('analyticsAnalyticsTranscriptsStats.noTranscriptDetails') }), jsx("p", { className: "text-sm mt-1", children: t('analyticsAnalyticsTranscriptsStats.unableToLoadTranscript') })] }) })) : (
|
|
231574
232763
|
/* Data loaded successfully */
|
|
231575
|
-
jsxs(Fragment$1, { children: [jsxs("div", { className: "mb-4 flex-shrink-0", children: [jsx("h2", { className: "text-lg font-semibold mb-2", children: t('analyticsAnalyticsTranscriptsStats.conversationTranscript') }), jsxs("div", { className: "text-sm text-gray-500", children: [jsxs("div", { children: [t('analyticsAnalyticsTranscriptsStats.
|
|
232764
|
+
jsxs(Fragment$1, { children: [jsxs("div", { className: "mb-4 flex-shrink-0", children: [jsx("h2", { className: "text-lg font-semibold mb-2", children: t('analyticsAnalyticsTranscriptsStats.conversationTranscript') }), jsxs("div", { className: "text-sm text-gray-500", children: [jsxs("div", { children: [t('analyticsAnalyticsTranscriptsStats.labelUser'), ' ', jsx(UserProfileLink, { currentSPA: currentSPA, tenantKey: tenantKey, username: (_a = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.summary) === null || _a === void 0 ? void 0 : _a.username, display: identifyUser(transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.summary) })] }), jsxs("div", { children: [t('analyticsAnalyticsTranscriptsStats.labelAgent'), ' ', jsx(AgentScopeLink, { uniqueId: (_b = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.summary) === null || _b === void 0 ? void 0 : _b.mentor_unique_id, name: (_c = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.summary) === null || _c === void 0 ? void 0 : _c.mentor })] }), jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [t('analyticsAnalyticsTranscriptsStats.labelModel'), ' ', ((_d = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.summary) === null || _d === void 0 ? void 0 : _d.model)
|
|
232765
|
+
? ((_e = turnDetails === null || turnDetails === void 0 ? void 0 : turnDetails.renderModel) !== null && _e !== void 0 ? _e : renderModelBadge)({
|
|
232766
|
+
model: transcriptsMessagesDetailsData.summary.model,
|
|
232767
|
+
provider: (_f = providerOf(transcriptsMessagesDetailsData.summary)) !== null && _f !== void 0 ? _f : providerOfTurns(transcriptsMessagesDetailsData.messages),
|
|
232768
|
+
})
|
|
232769
|
+
: '-'] }), jsx(TranscriptDocumentsButton, { detail: transcriptsMessagesDetailsData, className: "mt-2" })] })] }), jsx("div", { className: "flex-1 overflow-y-auto space-y-4 min-h-0", children: ((_g = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.messages) === null || _g === void 0 ? void 0 : _g.length) > 0 ? ((_h = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.messages) === null || _h === void 0 ? void 0 : _h.map((message, index) => {
|
|
231576
232770
|
var _a, _b;
|
|
231577
|
-
return (jsxs(React__default.Fragment, { children: [((message === null || message === void 0 ? void 0 : message.human) || !!((_a = message === null || message === void 0 ? void 0 : message.human_files) === null || _a === void 0 ? void 0 : _a.length)) && (jsxs("div", { className: `p-3 rounded-lg bg-blue-100 ml-4`, children: [jsx("div", { className: "flex justify-between items-start mb-1", children: jsx("span", { className: "font-medium text-sm", children: t('analyticsAnalyticsTranscriptsStats.roleUser') }) }), message.human && (jsx("p", { className: "text-sm", children: getMessageContent(message.human) })), jsx(TranscriptFiles, { files: message.human_files })] }, `${index}-human`)), ((message === null || message === void 0 ? void 0 : message.ai) || !!((_b = message === null || message === void 0 ? void 0 : message.ai_files) === null || _b === void 0 ? void 0 : _b.length)) && (jsxs("div", { className: `p-3 rounded-lg bg-white mr-4`, children: [jsx("div", { className: "flex justify-between items-start mb-1", children: jsx("span", { className: "font-medium text-sm", children: t('analyticsAnalyticsTranscriptsStats.roleAgent') }) }), message.ai && jsx(Markdown, { children: getMessageContent(message.ai) }), jsx(TranscriptFiles, { files: message.ai_files })] }, `${index}-ai`))] }, index));
|
|
232771
|
+
return (jsxs(React__default.Fragment, { children: [((message === null || message === void 0 ? void 0 : message.human) || !!((_a = message === null || message === void 0 ? void 0 : message.human_files) === null || _a === void 0 ? void 0 : _a.length)) && (jsxs("div", { className: `p-3 rounded-lg bg-blue-100 ml-4`, children: [jsx("div", { className: "flex justify-between items-start mb-1", children: jsx("span", { className: "font-medium text-sm", children: t('analyticsAnalyticsTranscriptsStats.roleUser') }) }), message.human && (jsx("p", { className: "text-sm", children: getMessageContent(message.human) })), jsx(TranscriptFiles, { files: message.human_files })] }, `${index}-human`)), ((message === null || message === void 0 ? void 0 : message.ai) || !!((_b = message === null || message === void 0 ? void 0 : message.ai_files) === null || _b === void 0 ? void 0 : _b.length)) && (jsxs("div", { className: `p-3 rounded-lg bg-white mr-4`, children: [jsx("div", { className: "flex justify-between items-start mb-1", children: jsx("span", { className: "font-medium text-sm", children: t('analyticsAnalyticsTranscriptsStats.roleAgent') }) }), message.ai && jsx(Markdown, { children: getMessageContent(message.ai) }), jsx(TranscriptFiles, { files: message.ai_files }), jsx(TranscriptTurnDetails, { turn: message, ...turnDetails })] }, `${index}-ai`))] }, index));
|
|
231578
232772
|
})) : (jsx("div", { className: "text-center text-gray-500 py-8", children: jsx("p", { children: t('analyticsAnalyticsTranscriptsStats.noMessages') }) })) })] })) }));
|
|
231579
232773
|
};
|
|
231580
232774
|
return (jsxs("div", { className: "space-y-8", children: [jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 mb-6", children: [jsx(StatCard, { title: t('analyticsAnalyticsTranscriptsStats.avgMessagesPerConversation'), value: ((_a = transcriptsConversationHeadlineData === null || transcriptsConversationHeadlineData === void 0 ? void 0 : transcriptsConversationHeadlineData.avg_messages_per_conversation) === null || _a === void 0 ? void 0 : _a.value) || 0, percentage: ((_b = transcriptsConversationHeadlineData === null || transcriptsConversationHeadlineData === void 0 ? void 0 : transcriptsConversationHeadlineData.avg_messages_per_conversation) === null || _b === void 0 ? void 0 : _b.percentage_change) ||
|
|
@@ -231584,11 +232778,11 @@ function AnalyticsTranscriptsStats({ tenantKey, currentSPA, mentorId, selectedMe
|
|
|
231584
232778
|
jsx("div", { className: "space-y-4", children: Array.from({ length: 3 }).map((_, index) => (jsxs(Card, { className: "p-4 animate-pulse", children: [jsx("div", { className: "mb-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-3/4" }) }), jsxs("div", { className: "flex flex-wrap gap-2 mb-3", children: [jsx("div", { className: "h-6 bg-gray-200 rounded w-16" }), jsx("div", { className: "h-6 bg-gray-200 rounded w-20" })] }), jsxs("div", { className: "flex flex-wrap gap-x-6 gap-y-2 mb-2", children: [jsx("div", { className: "h-4 bg-gray-200 rounded w-24" }), jsx("div", { className: "h-4 bg-gray-200 rounded w-20" })] }), jsxs("div", { className: "flex flex-wrap gap-x-6 gap-y-2", children: [jsx("div", { className: "h-4 bg-gray-200 rounded w-20" }), jsx("div", { className: "h-4 bg-gray-200 rounded w-24" })] })] }, index))) })) : (transcriptsMessagesData === null || transcriptsMessagesData === void 0 ? void 0 : transcriptsMessagesData.results) && transcriptsMessagesData.results.length > 0 ? (
|
|
231585
232779
|
// Results
|
|
231586
232780
|
transcriptsMessagesData.results.map((transcript) => {
|
|
231587
|
-
var _a, _b;
|
|
232781
|
+
var _a, _b, _c;
|
|
231588
232782
|
return (jsxs(Card, { className: cn(`p-4 hover:shadow-md transition-shadow cursor-pointer border ${selectedTranscript === transcript.session
|
|
231589
232783
|
? 'border-blue-500 bg-blue-50'
|
|
231590
|
-
: 'border-gray-200'}`), onClick: () => handleTranscriptSelect(transcript.session), children: [jsx("div", { className: "mb-3", children: jsx("p", { className: "text-gray-800", children: transcript.first_user_message }) }),
|
|
231591
|
-
|
|
232784
|
+
: 'border-gray-200'}`), onClick: () => handleTranscriptSelect(transcript.session), children: [jsx("div", { className: "mb-3", children: jsx("p", { className: "text-gray-800", children: transcript.first_user_message }) }), jsxs("div", { className: "flex flex-wrap gap-2 mb-3", children: [((_a = transcript === null || transcript === void 0 ? void 0 : transcript.topics) === null || _a === void 0 ? void 0 : _a.length) > 0 &&
|
|
232785
|
+
((_b = transcript.topics) === null || _b === void 0 ? void 0 : _b.map((topic, index) => (jsx("span", { className: "bg-gray-100 text-gray-600 px-3 py-1 rounded-[5px] text-xs", children: topic }, index)))), jsx(TranscriptRollupBadges, { documentsCount: transcript.documents_count, toolCallsCount: transcript.tool_calls_count })] }), jsx("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-2 text-sm mb-2", children: jsxs("div", { className: cn('flex items-center gap-1', transcript.sentiment === 'negative'
|
|
231592
232786
|
? 'text-blue-600'
|
|
231593
232787
|
: transcript.sentiment === 'positive'
|
|
231594
232788
|
? 'text-green-600'
|
|
@@ -231596,7 +232790,12 @@ function AnalyticsTranscriptsStats({ tenantKey, currentSPA, mentorId, selectedMe
|
|
|
231596
232790
|
? t('analyticsAnalyticsTranscriptsStats.sentimentNegative')
|
|
231597
232791
|
: transcript.sentiment === 'positive'
|
|
231598
232792
|
? t('analyticsAnalyticsTranscriptsStats.sentimentPositive')
|
|
231599
|
-
: t('analyticsAnalyticsTranscriptsStats.sentimentNeutral'), ' ', t('analyticsAnalyticsTranscriptsStats.userSentiment')] })] }) }), jsxs("div", { className: "flex flex-wrap gap-x-6 gap-y-2 text-xs text-gray-500 mb-2", children: [jsxs("div", { children: [t('analyticsAnalyticsTranscriptsStats.labelUser'), ' ', jsx(UserProfileLink, { currentSPA: currentSPA, tenantKey: tenantKey, username: transcript === null || transcript === void 0 ? void 0 : transcript.username, display: identifyUser(transcript
|
|
232793
|
+
: t('analyticsAnalyticsTranscriptsStats.sentimentNeutral'), ' ', t('analyticsAnalyticsTranscriptsStats.userSentiment')] })] }) }), jsxs("div", { className: "flex flex-wrap gap-x-6 gap-y-2 text-xs text-gray-500 mb-2", children: [jsxs("div", { children: [t('analyticsAnalyticsTranscriptsStats.labelUser'), ' ', jsx(UserProfileLink, { currentSPA: currentSPA, tenantKey: tenantKey, username: transcript === null || transcript === void 0 ? void 0 : transcript.username, display: identifyUser(transcript) })] }), jsxs("div", { children: [t('analyticsAnalyticsTranscriptsStats.labelAgent'), ' ', jsx(AgentScopeLink, { uniqueId: transcript === null || transcript === void 0 ? void 0 : transcript.mentor_unique_id, name: transcript === null || transcript === void 0 ? void 0 : transcript.mentor })] })] }), jsx("div", { className: "flex flex-wrap gap-x-6 gap-y-2 text-xs text-gray-500 mb-2", children: jsxs("div", { className: "inline-flex flex-wrap items-center gap-1.5", children: [t('analyticsAnalyticsTranscriptsStats.labelModelCard'), ' ', (transcript === null || transcript === void 0 ? void 0 : transcript.model)
|
|
232794
|
+
? ((_c = turnDetails === null || turnDetails === void 0 ? void 0 : turnDetails.renderModel) !== null && _c !== void 0 ? _c : renderModelBadge)({
|
|
232795
|
+
model: transcript.model,
|
|
232796
|
+
provider: providerOf(transcript),
|
|
232797
|
+
})
|
|
232798
|
+
: '-'] }) }), jsxs("div", { className: "flex flex-wrap gap-x-6 gap-y-2 text-xs text-gray-500", children: [jsxs("div", { children: [transcript.message_count, " ", t('analyticsAnalyticsTranscriptsStats.messages')] }), jsx("div", { children: "\u2022" }), jsxs("div", { children: ["$", Number((transcript === null || transcript === void 0 ? void 0 : transcript.cost) || 0).toFixed(2), ' ', t('analyticsAnalyticsTranscriptsStats.estimatedCost')] }), (transcript === null || transcript === void 0 ? void 0 : transcript.created_at) && (jsxs(Fragment$1, { children: [jsx("div", { children: "\u2022" }), jsxs("div", { children: [t('analyticsAnalyticsTranscriptsStats.created'), ' ', formatRelativeTime(transcript.created_at, t)] })] }))] })] }, transcript.session));
|
|
231600
232799
|
})) : (
|
|
231601
232800
|
// Empty state
|
|
231602
232801
|
jsx("div", { className: "text-center py-12", children: jsx("p", { className: "text-gray-500", children: filters.topicSearch || filters.userSearch || filters.rating
|
|
@@ -231632,9 +232831,14 @@ function AnalyticsTranscriptsStats({ tenantKey, currentSPA, mentorId, selectedMe
|
|
|
231632
232831
|
/* Error or no data state */
|
|
231633
232832
|
jsx("div", { className: "flex items-center justify-center h-full text-gray-400", children: jsxs("div", { className: "text-center", children: [jsx(X$1, { className: "h-6 w-6 mx-auto mb-2 text-red-400" }), jsx("p", { children: t('analyticsAnalyticsTranscriptsStats.noTranscriptDetails') }), jsx("p", { className: "text-sm mt-1", children: t('analyticsAnalyticsTranscriptsStats.unableToLoadTranscript') })] }) })) : (
|
|
231634
232833
|
/* Data loaded successfully */
|
|
231635
|
-
jsxs("div", { className: "space-y-4", children: [jsx("div", { className: "mb-4", children: jsxs("div", { className: "text-sm text-gray-500 space-y-1", children: [jsxs("div", { children: [t('analyticsAnalyticsTranscriptsStats.
|
|
232834
|
+
jsxs("div", { className: "space-y-4", children: [jsx("div", { className: "mb-4", children: jsxs("div", { className: "text-sm text-gray-500 space-y-1", children: [jsxs("div", { children: [t('analyticsAnalyticsTranscriptsStats.labelUser'), ' ', jsx(UserProfileLink, { currentSPA: currentSPA, tenantKey: tenantKey, username: (_g = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.summary) === null || _g === void 0 ? void 0 : _g.username, display: identifyUser(transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.summary) })] }), jsxs("div", { children: [t('analyticsAnalyticsTranscriptsStats.labelAgent'), ' ', jsx(AgentScopeLink, { uniqueId: (_h = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.summary) === null || _h === void 0 ? void 0 : _h.mentor_unique_id, name: (_j = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.summary) === null || _j === void 0 ? void 0 : _j.mentor })] }), jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [t('analyticsAnalyticsTranscriptsStats.labelModel'), ' ', ((_k = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.summary) === null || _k === void 0 ? void 0 : _k.model)
|
|
232835
|
+
? ((_l = turnDetails === null || turnDetails === void 0 ? void 0 : turnDetails.renderModel) !== null && _l !== void 0 ? _l : renderModelBadge)({
|
|
232836
|
+
model: transcriptsMessagesDetailsData.summary.model,
|
|
232837
|
+
provider: (_m = providerOf(transcriptsMessagesDetailsData.summary)) !== null && _m !== void 0 ? _m : providerOfTurns(transcriptsMessagesDetailsData.messages),
|
|
232838
|
+
})
|
|
232839
|
+
: '-'] }), jsx(TranscriptDocumentsButton, { detail: transcriptsMessagesDetailsData, className: "mt-2" })] }) }), jsx("div", { className: "space-y-4 pb-4", children: ((_o = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.messages) === null || _o === void 0 ? void 0 : _o.length) > 0 ? ((_p = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.messages) === null || _p === void 0 ? void 0 : _p.map((message, index) => {
|
|
231636
232840
|
var _a, _b;
|
|
231637
|
-
return (jsxs(React__default.Fragment, { children: [((message === null || message === void 0 ? void 0 : message.human) || !!((_a = message === null || message === void 0 ? void 0 : message.human_files) === null || _a === void 0 ? void 0 : _a.length)) && (jsxs("div", { className: "p-3 rounded-lg bg-blue-100 ml-4", children: [jsx("div", { className: "flex justify-between items-start mb-1", children: jsx("span", { className: "font-medium text-sm", children: t('analyticsAnalyticsTranscriptsStats.roleUser') }) }), message.human && (jsx("p", { className: "text-sm", children: getMessageContent(message.human) })), jsx(TranscriptFiles, { files: message.human_files })] })), ((message === null || message === void 0 ? void 0 : message.ai) || !!((_b = message === null || message === void 0 ? void 0 : message.ai_files) === null || _b === void 0 ? void 0 : _b.length)) && (jsxs("div", { className: "p-3 rounded-lg bg-white mr-4 border", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx("div", { className: "flex justify-between items-start mb-1", children: jsx("span", { className: "font-medium text-sm", children: t('analyticsAnalyticsTranscriptsStats.roleAgent') }) }), message.ai && jsx(Markdown, { children: getMessageContent(message.ai) }), jsx(TranscriptFiles, { files: message.ai_files })] }))] }, index));
|
|
232841
|
+
return (jsxs(React__default.Fragment, { children: [((message === null || message === void 0 ? void 0 : message.human) || !!((_a = message === null || message === void 0 ? void 0 : message.human_files) === null || _a === void 0 ? void 0 : _a.length)) && (jsxs("div", { className: "p-3 rounded-lg bg-blue-100 ml-4", children: [jsx("div", { className: "flex justify-between items-start mb-1", children: jsx("span", { className: "font-medium text-sm", children: t('analyticsAnalyticsTranscriptsStats.roleUser') }) }), message.human && (jsx("p", { className: "text-sm", children: getMessageContent(message.human) })), jsx(TranscriptFiles, { files: message.human_files })] })), ((message === null || message === void 0 ? void 0 : message.ai) || !!((_b = message === null || message === void 0 ? void 0 : message.ai_files) === null || _b === void 0 ? void 0 : _b.length)) && (jsxs("div", { className: "p-3 rounded-lg bg-white mr-4 border", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx("div", { className: "flex justify-between items-start mb-1", children: jsx("span", { className: "font-medium text-sm", children: t('analyticsAnalyticsTranscriptsStats.roleAgent') }) }), message.ai && jsx(Markdown, { children: getMessageContent(message.ai) }), jsx(TranscriptFiles, { files: message.ai_files }), jsx(TranscriptTurnDetails, { turn: message, ...turnDetails })] }))] }, index));
|
|
231638
232842
|
})) : (jsx("div", { className: "text-center text-gray-500 py-8", children: jsx("p", { children: t('analyticsAnalyticsTranscriptsStats.noMessages') }) })) })] })) })] }) }))] }));
|
|
231639
232843
|
}
|
|
231640
232844
|
|
|
@@ -240511,64 +241715,6 @@ const AutoResizeTextarea = ({ allowEmptySubmit = false, value, onChange, onSubmi
|
|
|
240511
241715
|
disabled, placeholder: placeholder, style: combinedStyle, className: `flex max-h-32 min-h-[36px] w-full resize-none rounded-2xl border-0 border-gray-200 bg-transparent px-4 py-2 pt-2 pb-1 text-base ring-offset-white placeholder:text-gray-400 focus:outline-none focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-800 dark:bg-gray-950 dark:ring-offset-gray-950 dark:placeholder:text-gray-400 ${className}`, ...props }));
|
|
240512
241716
|
};
|
|
240513
241717
|
|
|
240514
|
-
function DocumentSidebar({ isModal = false, sessionId }) {
|
|
240515
|
-
const t = useT();
|
|
240516
|
-
const [isCollapsed, setIsCollapsed] = React.useState(false);
|
|
240517
|
-
const params = useParams();
|
|
240518
|
-
const username = useUsername();
|
|
240519
|
-
const isStreaming = useSelector(selectStreaming);
|
|
240520
|
-
const { data: vectorDocuments, refetch, status, } = useGetVectorDocumentsQuery({
|
|
240521
|
-
org: params.tenantKey,
|
|
240522
|
-
sessionId: sessionId,
|
|
240523
|
-
// @ts-ignore
|
|
240524
|
-
userId: username,
|
|
240525
|
-
}, {
|
|
240526
|
-
skip: !params.tenantKey || !sessionId || !username || !isLoggedIn(),
|
|
240527
|
-
});
|
|
240528
|
-
React.useEffect(() => {
|
|
240529
|
-
if (!isStreaming && isLoggedIn() && status !== 'uninitialized') {
|
|
240530
|
-
refetch();
|
|
240531
|
-
}
|
|
240532
|
-
}, [isStreaming, refetch]);
|
|
240533
|
-
const toggleCollapse = () => {
|
|
240534
|
-
setIsCollapsed(!isCollapsed);
|
|
240535
|
-
};
|
|
240536
|
-
return (jsx(Fragment$1, { children: (vectorDocuments === null || vectorDocuments === void 0 ? void 0 : vectorDocuments.length) && vectorDocuments.length > 0 ? (jsx("aside", { className: cn('transition-all duration-300 ease-in-out', isModal
|
|
240537
|
-
? 'max-h-full w-full overflow-auto'
|
|
240538
|
-
: 'hidden rounded-tl-lg rounded-bl-lg md:hidden lg:block', !isModal && (isCollapsed ? 'w-[40px]' : 'w-[380px]')), style: {
|
|
240539
|
-
backgroundColor: isCollapsed && !isModal ? 'white' : '#F3F6FB',
|
|
240540
|
-
maxHeight: 'calc(100vh - 80px)',
|
|
240541
|
-
}, children: jsxs("div", { className: "flex h-full flex-col", children: [!isModal && (jsxs("div", { className: cn('flex cursor-pointer items-center gap-2 border-b border-gray-200 p-4 transition-colors duration-200', isCollapsed && 'h-[80px] justify-center rounded-tl-[5px] rounded-bl-[5px] p-2', 'hover:bg-blue-100'), onClick: toggleCollapse, style: { backgroundColor: '#F3F6FB' }, children: [jsx(FileText, { className: "h-5 w-5 shrink-0 text-blue-600" }), !isCollapsed && (jsxs(Fragment$1, { children: [jsx("h2", { className: "text-base font-medium text-[#646464]", children: t('documentSidebar.retrievedDocuments') }), jsx(ChevronRight, { className: cn('ml-auto h-4 w-4 text-gray-400 transition-transform', isCollapsed ? 'rotate-180' : '') })] }))] })), (!isCollapsed || isModal) && (jsx(Fragment$1, { children: jsx("div", { className: "flex-1 overflow-auto", style: { backgroundColor: '#F3F6FB' }, children: jsx("div", { className: "mt-0 space-y-1 p-2", children: vectorDocuments.map((doc, index) => {
|
|
240542
|
-
var _a, _b;
|
|
240543
|
-
return (jsxs(React.Fragment, { children: [jsx("div", { className: "rounded-lg p-2 hover:bg-gray-50", children: jsxs("div", { className: "flex items-start gap-2", children: [jsx(Radio$1, { className: "mt-1 h-4 w-4 text-gray-400" }), jsxs("div", { className: "min-w-0 flex-1 space-y-1", children: [jsxs("div", { className: "flex items-center justify-between", children: [jsx(Link$2, { href: (_a = doc.source) !== null && _a !== void 0 ? _a : '', target: "_blank", className: "min-w-0", children: jsx("span", { className: "text-sm font-semibold break-words text-[#646464] hover:text-blue-600", children: doc.title }) }), jsx("div", { className: "flex items-center gap-2 self-center", children: jsx("span", { className: "text-xs text-gray-500", children: (_b = doc === null || doc === void 0 ? void 0 : doc.score) === null || _b === void 0 ? void 0 : _b.toFixed(2) }) })] }), jsx("p", { className: "line-clamp-6 pt-[10px] text-[14px] text-gray-600", children: doc.snippet })] })] }) }), index < vectorDocuments.length - 1 && (jsx("div", { className: "my-2 border-t border-gray-200" }))] }, index));
|
|
240544
|
-
}) }) }) }))] }) })) : null }));
|
|
240545
|
-
}
|
|
240546
|
-
|
|
240547
|
-
function RetrievedDocumentsButton({ sessionId }) {
|
|
240548
|
-
const t = useT();
|
|
240549
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
240550
|
-
const params = useParams();
|
|
240551
|
-
const username = useUsername();
|
|
240552
|
-
const isStreaming = useSelector(selectStreaming);
|
|
240553
|
-
const { data: vectorDocuments, refetch, status, } = useGetVectorDocumentsQuery({
|
|
240554
|
-
org: params.tenantKey,
|
|
240555
|
-
sessionId: sessionId,
|
|
240556
|
-
// @ts-ignore
|
|
240557
|
-
userId: username,
|
|
240558
|
-
}, {
|
|
240559
|
-
skip: !params.tenantKey || !sessionId || !username || !isLoggedIn(),
|
|
240560
|
-
});
|
|
240561
|
-
useEffect(() => {
|
|
240562
|
-
if (!isStreaming && isLoggedIn() && status !== 'uninitialized') {
|
|
240563
|
-
refetch();
|
|
240564
|
-
}
|
|
240565
|
-
}, [isStreaming, refetch]);
|
|
240566
|
-
if (!(vectorDocuments === null || vectorDocuments === void 0 ? void 0 : vectorDocuments.length)) {
|
|
240567
|
-
return null;
|
|
240568
|
-
}
|
|
240569
|
-
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 }) })] }) })] }));
|
|
240570
|
-
}
|
|
240571
|
-
|
|
240572
241718
|
const PAGE_SIZE = 10;
|
|
240573
241719
|
const MemoryMenu = ({ onClose, mentorId, tenantKey, username }) => {
|
|
240574
241720
|
const t = useT();
|
|
@@ -246092,5 +247238,5 @@ var trainOrDeleteModal = /*#__PURE__*/Object.freeze({
|
|
|
246092
247238
|
TrainOrDeleteModal: TrainOrDeleteModal
|
|
246093
247239
|
});
|
|
246094
247240
|
|
|
246095
|
-
export { ACCESS_COURSE_LABEL, ALL_CATEGORIES, AccessTimeHeatmap, AccessiblePaginate, AddMentorToProjectModal, AddSkillDialog, Admin, AdvancedTab, AgentConfigPrompts, AgentScopeLink, AgentSkills, AlertsTab, AnalyticsAgentPicker, AnalyticsAreaChart, AnalyticsAuditLogStats, AnalyticsBarChart, AnalyticsControlBar, AnalyticsCourseDetail, AnalyticsCourses, AnalyticsFinancialStats, AnalyticsGlobalFiltersProvider, AnalyticsLayout, AnalyticsLlmUsageStats, AnalyticsMemoryStats, AnalyticsMonetizationStats, AnalyticsNotice, AnalyticsOverview, AnalyticsPlatformAuditLog, AnalyticsProgramDetail, AnalyticsPrograms, AnalyticsReportDownload, AnalyticsReports, AnalyticsScopeProvider, AnalyticsSettingsProvider, AnalyticsTopicsStats, AnalyticsTraces, AnalyticsTranscriptsStats, AnalyticsUsersStats, AppleRestrictionModal, ApplyWizard, AuditLogChangesView, AuditLogJsonView, BUY_NOW_LABEL, BillingTab, CATALOGS, CHART_ORDINAL_RAMP, CHART_SERIES_COLORS, CHART_SINGLE_SERIES_COLOR, CREATE_AGENT_LABELS, CUA_DRIVER_REPO_URL, CUA_DRIVER_TAURI_COMMANDS, CUA_DRIVER_TAURI_EVENTS, CardInfoIcon, CategorizedDropdownMenu, ChartCardWrapper, ChartFiltersProvider, ChartLoading, ChartTooltipCard, ChatContext, ChatPrivacyToggle, ChatProvider, CompanyDialog, ConnectorManagementDialog, CopyButtonIcon, CourseAccessGuard, CourseCardSkeleton, CourseContentLoading, CourseOutline, CourseOutlineContext, CourseOutlineDrawer, CreateAgentForm, CreateAgentModal, CreateProjectModal, CreateWorkflowModal, CredentialBox, CredentialMiniBoxSkeleton, CredentialsList, CreditBalance, CustomDateRangePicker, CustomTooltip, DEFAULT_COWORK_REQUIRED_SIZE_GB, DEFAULT_LOCALE, DefaultEmptyBox, DeleteProjectModal, DeleteWorkflowModal, DiscoverContentCard, DiscoverFacetsFilter, DiscoverFilterDrawer, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, ENROLL_NOW_COURSE_STARTING_SOON_LABEL, ENROLL_NOW_LABEL, EditAlertDialog, EducationBox, EducationDialog, EducationTab, EdxIframeContext, EmptyStats, ExperienceBox, ExperienceDialog, ExperienceTab, FacetFilterContext, Footer, GradebookTab, GroupsFilterDropdown, INVITATION_ONLY_LABEL, InstitutionDialog, IntegrationsTab, InviteUserContent, InviteUserDialog, InvitedUsersDialog, LOCAL_LLM_CHANGED_EVENT, LOCAL_MODELS, Loader, LocalLLMTab, LocalModelsContent, LoginButton, MACOS_PERMISSIONS_COMMANDS, MEMORY_PAGE_SIZE, Markdown, MemoryAdminTab, MinimumMentorAlert, MonetizationTab, NotificationDisplay, NotificationDropdown, ONBOARDING_FIELD_TYPES, ONBOARDING_SECTORS, OnboardingField, OnboardingShell, OnboardingWizard, PLATFORM_AUDIT_DEEP_PAGING_THRESHOLD, PLATFORM_AUDIT_PAGE_SIZE, PaywallModal, PlacementExam, PlacementExamsDropdown, PlatformAuditLogDetailSheet, PlatformNavbar, PlatformNavbarSearch, Profile, ProfileTimeChart, ProgressDots, ProjectActionButtons, ProjectFilesModal, ProjectInstructionsModal, ProjectLandingPage, ProjectMentorsList, ProjectsPage, REQUEST_ACCESS_COURSE_STARTING_SOON_LABEL, REQUEST_ACCESS_LABEL, RankedBars, RenameProjectModal, ResumeBox, ResumeTab, RichTextEditor, SERVICE_COLOR_ORDER, SUPPORTED_LOCALES, SandboxConfig, SearchableMultiSelect, SendNotificationDialog, SignupButton, SkeletonActivityStatBox, SkeletonAddSkillsLoading, SkeletonCreatePathwaySearchList, SkeletonDiscoverFilterBox, SkeletonEducationBox, SkeletonMultiplier, SkeletonPathwayBox, SkeletonProfileInfoCard, SkeletonSkillBox, SkillBox, SkillDetailModal, SkillLeaderboardChart, SkillsBox, SkillsList, SlashSkillPicker, SourceChip, Spinner, StatCard, StepHeader, SummerNoteTextEditor, TAURI_COMMANDS, TAURI_EVENTS, TRACES_PAGE_SIZE, TenantSwitcher, TimeFilter, TimeTrackingProvider, TimedExam, ToolDialogs, TopBanner, TrendSparkline, USER_ONBOARDING_FORM_SLUG, USER_ONBOARDING_FORM_VERSION, USER_ONBOARDING_SUBMISSION_SLUG, UpgradePackageModal, UserAvatar, UserOnboardingWizard, Version, WebContainersI18nProvider, WorkflowSidebar, addBookmarksTab, areChartFiltersEqual, availablePlacementExams, buildOnboardingAgentPath, buildUserOnboardingFormMetadata, buildUserOnboardingSubmissionMetadata, coerceOnboardingAgent, coerceOnboardingAgents, coerceUserOnboardingForm, colorForRank, colorForSeries, emptyUserOnboardingForm, findLastResumeBlock, findOnboardingAgent, findSequentialParent, flattenVerticalBlocks, formatAuditTimestamp, formatCompactNumber, formatLatencySeconds, formatTimeZoneLabel, getCatalog, getFirstAvailableUnit, getLocalLLMModel, getLocalLLMToolSupport, getNextUnitIframe, getOrg, getParentBlockById, getParentsInfosFromSublessonId, getPreviousUnitIframe, getRandomCourseImage, getSectorById, getTenant, getUnitToIframe, getUserId, getUserName, granularityForFilter, hasOnboardingContent, humanizeAuditToken, inBrowserPrint, inIframe, initialCuaDriverInstallState, initialModelDownloadState, isCoworkEnabled, isLlmUsageForbidden, isLlmUsageUnavailable, isLocalLLMEnabled, isPlatformNavbarCreditBalanceVisible, isSlashCommandToken, isTauriApp, isValidLocale, isValidTimeZone, llmUsageDateArgs, components as markdownComponents, modelSupportsCowork, onboardingPrimaryButtonClass, onboardingSecondaryButtonClass, readUserOnboardingForm, readUserOnboardingSubmission, readUserOnboardingSubmissions, resolveAuditTimeZone, resolveCreateAgentLabels, sanitizeCss, setCoworkEnabled, setLocalLLMEnabled, setLocalLLMModel, setLocalLLMToolSupport, smallestCoworkModel, useAnalyticsGlobalFilters, useAnalyticsScope, useAnalyticsSettings, useAuditLog, useCatalogSearch, useChartFilters, useChatPrivacy, useChatState, useCourseDetail, useCourseMetadata, useCourses, useCuaDriver, useDiscover, useEdxIframe, useFinancial, useIframeMessageHandler, useLlmTraces, useLlmUsage, useLocalStorage, useMemory, useModelDownload, useMonetization, useOverview, usePlatformAuditLabels, usePlatformAuditLog, useProfileActivityStats, useProfileCredentials, useProfilePathways, useProfilePrograms, useProfileSkills, useProfileTimeSpent, usePrograms, useReports, useScopedMentorDbId, useScopedMentorId, useSelectedLocalModel, useSlashSkillPicker, useSlashSkills, useT, useTauri, useTimeTracking, useTopics, useTranscripts, useUserCourses, useUserMetadata, useUsers, useWebContainersI18n, useWebContainersLocale };
|
|
247241
|
+
export { ACCESS_COURSE_LABEL, ALL_CATEGORIES, AccessTimeHeatmap, AccessiblePaginate, AddMentorToProjectModal, AddSkillDialog, Admin, AdvancedTab, AgentConfigPrompts, AgentScopeLink, AgentSkills, AlertsTab, AnalyticsAgentPicker, AnalyticsAreaChart, AnalyticsAuditLogStats, AnalyticsBarChart, AnalyticsControlBar, AnalyticsCourseDetail, AnalyticsCourses, AnalyticsFinancialStats, AnalyticsGlobalFiltersProvider, AnalyticsLayout, AnalyticsLlmUsageStats, AnalyticsMemoryStats, AnalyticsMonetizationStats, AnalyticsNotice, AnalyticsOverview, AnalyticsPlatformAuditLog, AnalyticsProgramDetail, AnalyticsPrograms, AnalyticsReportDownload, AnalyticsReports, AnalyticsScopeProvider, AnalyticsSettingsProvider, AnalyticsTopicsStats, AnalyticsTraces, AnalyticsTranscriptsStats, AnalyticsUsersStats, AppleRestrictionModal, ApplyWizard, AuditLogChangesView, AuditLogJsonView, BUY_NOW_LABEL, BillingTab, CATALOGS, CHART_ORDINAL_RAMP, CHART_SERIES_COLORS, CHART_SINGLE_SERIES_COLOR, CREATE_AGENT_LABELS, CUA_DRIVER_REPO_URL, CUA_DRIVER_TAURI_COMMANDS, CUA_DRIVER_TAURI_EVENTS, CardInfoIcon, CategorizedDropdownMenu, ChartCardWrapper, ChartFiltersProvider, ChartLoading, ChartTooltipCard, ChatContext, ChatPrivacyToggle, ChatProvider, CompanyDialog, ConnectorManagementDialog, CopyButtonIcon, CourseAccessGuard, CourseCardSkeleton, CourseContentLoading, CourseOutline, CourseOutlineContext, CourseOutlineDrawer, CreateAgentForm, CreateAgentModal, CreateProjectModal, CreateWorkflowModal, CredentialBox, CredentialMiniBoxSkeleton, CredentialsList, CreditBalance, CustomDateRangePicker, CustomTooltip, DEFAULT_COWORK_REQUIRED_SIZE_GB, DEFAULT_LOCALE, DEFAULT_USER_IDENTITY_ORDER, DefaultEmptyBox, DeleteProjectModal, DeleteWorkflowModal, DiscoverContentCard, DiscoverFacetsFilter, DiscoverFilterDrawer, DocumentSidebar, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, ENROLL_NOW_COURSE_STARTING_SOON_LABEL, ENROLL_NOW_LABEL, EditAlertDialog, EducationBox, EducationDialog, EducationTab, EdxIframeContext, EmptyStats, ExperienceBox, ExperienceDialog, ExperienceTab, FacetFilterContext, Footer, GradebookTab, GroupsFilterDropdown, INVITATION_ONLY_LABEL, InstitutionDialog, IntegrationsTab, InviteUserContent, InviteUserDialog, InvitedUsersDialog, LOCAL_LLM_CHANGED_EVENT, LOCAL_MODELS, LlmModelBadge, Loader, LocalLLMTab, LocalModelsContent, LoginButton, MACOS_PERMISSIONS_COMMANDS, MEMORY_PAGE_SIZE, Markdown, MemoryAdminTab, MinimumMentorAlert, MonetizationTab, NotificationDisplay, NotificationDropdown, ONBOARDING_FIELD_TYPES, ONBOARDING_SECTORS, OnboardingField, OnboardingShell, OnboardingWizard, PLATFORM_AUDIT_DEEP_PAGING_THRESHOLD, PLATFORM_AUDIT_PAGE_SIZE, PaywallModal, PlacementExam, PlacementExamsDropdown, PlatformAuditLogDetailSheet, PlatformNavbar, PlatformNavbarSearch, Profile, ProfileTimeChart, ProgressDots, ProjectActionButtons, ProjectFilesModal, ProjectInstructionsModal, ProjectLandingPage, ProjectMentorsList, ProjectsPage, REQUEST_ACCESS_COURSE_STARTING_SOON_LABEL, REQUEST_ACCESS_LABEL, RankedBars, RenameProjectModal, ResumeBox, ResumeTab, RetrievedDocumentsButton, RichTextEditor, SERVICE_COLOR_ORDER, SUPPORTED_LOCALES, SandboxConfig, SearchableMultiSelect, SendNotificationDialog, SignupButton, SkeletonActivityStatBox, SkeletonAddSkillsLoading, SkeletonCreatePathwaySearchList, SkeletonDiscoverFilterBox, SkeletonEducationBox, SkeletonMultiplier, SkeletonPathwayBox, SkeletonProfileInfoCard, SkeletonSkillBox, SkillBox, SkillDetailModal, SkillLeaderboardChart, SkillsBox, SkillsList, SlashSkillPicker, SourceChip, Spinner, StatCard, StepHeader, SummerNoteTextEditor, TAURI_COMMANDS, TAURI_EVENTS, TRACES_PAGE_SIZE, TenantSwitcher, TimeFilter, TimeTrackingProvider, TimedExam, ToolCallIndicator, ToolDialogs, TopBanner, TranscriptFileCards, TranscriptRollupBadges, TranscriptTurnDetails, TrendSparkline, USER_ONBOARDING_FORM_SLUG, USER_ONBOARDING_FORM_VERSION, USER_ONBOARDING_SUBMISSION_SLUG, UpgradePackageModal, UserAvatar, UserOnboardingWizard, UserProfileDialog, UserProfileLink, Version, WebContainersI18nProvider, WorkflowSidebar, addBookmarksTab, areChartFiltersEqual, availablePlacementExams, buildOnboardingAgentPath, buildUserOnboardingFormMetadata, buildUserOnboardingSubmissionMetadata, coerceOnboardingAgent, coerceOnboardingAgents, coerceUserOnboardingForm, colorForRank, colorForSeries, conversationDocuments, emptyUserOnboardingForm, findLastResumeBlock, findOnboardingAgent, findSequentialParent, flattenVerticalBlocks, formatAuditTimestamp, formatCompactNumber, formatFileSize, formatLatencySeconds, formatResult, formatTimeZoneLabel, getCatalog, getFirstAvailableUnit, getFriendlyToolName, getLLMModelDisplayName, getLocalLLMModel, getLocalLLMToolSupport, getNextUnitIframe, getOrg, getParentBlockById, getParentsInfosFromSublessonId, getPreviousUnitIframe, getQueryLabel, getRandomCourseImage, getSectorById, getTenant, getUnitToIframe, getUserId, getUserName, granularityForFilter, hasOnboardingContent, humanizeAuditToken, humanizeFieldName, inBrowserPrint, inIframe, inferProviderKeysFromModel, initialCuaDriverInstallState, initialModelDownloadState, isCoworkEnabled, isEmailLike, isFileReference, isLlmUsageForbidden, isLlmUsageUnavailable, isLocalLLMEnabled, isPlatformNavbarCreditBalanceVisible, isSlashCommandToken, isTauriApp, isValidLocale, isValidTimeZone, llmUsageDateArgs, components as markdownComponents, modelSupportsCowork, onboardingPrimaryButtonClass, onboardingSecondaryButtonClass, readUserOnboardingForm, readUserOnboardingSubmission, readUserOnboardingSubmissions, resolveAuditTimeZone, resolveCreateAgentLabels, resolveUserIdentity, sanitizeCss, setCoworkEnabled, setLocalLLMEnabled, setLocalLLMModel, setLocalLLMToolSupport, smallestCoworkModel, summarizeTranscriptTurns, toFileReference, toRetrievedDocuments, toToolCallInfos, useAnalyticsGlobalFilters, useAnalyticsScope, useAnalyticsSettings, useAuditLog, useCatalogSearch, useChartFilters, useChatPrivacy, useChatState, useCourseDetail, useCourseMetadata, useCourses, useCuaDriver, useDiscover, useEdxIframe, useFinancial, useIframeMessageHandler, useLlmDisplayName, useLlmProviderCatalogue, useLlmTraces, useLlmUsage, useLocalStorage, useMemory, useModelDownload, useMonetization, useOverview, usePlatformAuditLabels, usePlatformAuditLog, useProfileActivityStats, useProfileCredentials, useProfilePathways, useProfilePrograms, useProfileSkills, useProfileTimeSpent, usePrograms, useReports, useScopedMentorDbId, useScopedMentorId, useSelectedLocalModel, useSlashSkillPicker, useSlashSkills, useT, useTauri, useTimeTracking, useTopics, useTranscripts, useUserCourses, useUserMetadata, useUsers, useWebContainersI18n, useWebContainersLocale };
|
|
246096
247242
|
//# sourceMappingURL=index.esm.js.map
|