@iblai/iblai-js 2.2.8 → 2.2.10
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 +1271 -931
- package/dist/web-containers/source/next/index.esm.js +1812 -1250
- package/package.json +6 -6
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import React__default, { useState, useEffect, forwardRef, createElement as createElement$3, useLayoutEffect, createContext, useContext, useMemo,
|
|
3
|
+
import React__default, { useState, useEffect, forwardRef, createElement as createElement$3, useLayoutEffect, createContext, useContext, useMemo, useReducer, useRef, useImperativeHandle, useCallback, isValidElement, Children, PureComponent, cloneElement, Component as Component$1, useId as useId$2, useDebugValue, lazy, Suspense } from 'react';
|
|
4
4
|
import * as dataLayer from '@iblai/data-layer';
|
|
5
|
-
import { useGetUserMetadataQuery, useGetUserMetadataEdxQuery, useUpdateUserMetadataMutation, useUpdateUserMetadataEdxMutation, useUploadProfileImageMutation, useResetPasswordMutation, useSelfRetireMutation, useCreateUserInstitutionMutation, useGetUserInstitutionsQuery, useCreateUserEducationMutation, useUpdateUserEducationMutation, useDeleteUserEducationMutation, useGetUserEducationQuery, useCreateUserCompanyMutation, useGetUserCompaniesQuery, useCreateUserExperienceMutation, useUpdateUserExperienceMutation, useDeleteUserExperienceMutation, useGetUserExperienceQuery, useGetUserResumeQuery, useCreateUserResumeMutation, useGetMySubscriptionsQuery, useGetItemSubscriptionQuery, useCancelSubscriptionMutation, useGetLearnerDetailsQuery, useGetUserEnrolledCoursesQuery, useGetUserEnrolledProgramsQuery, useGetUserCatalogPathwaysQuery, useGetUsersAsAssertionsQuery, useGetUserEarnedSkillsQuery, useGetUserReportedSkillsQuery, useGetUserDesiredSkillsQuery, useCreateGlobalMemoryMutation, useGetMemsearchStatusQuery, useGetUserMemorySettingsQuery, useUpdateUserMemorySettingsMutation, useGetGlobalMemoriesQuery, useDeleteGlobalMemoryMutation, useInviteUserMutation, usePlatformInvitationsQuery, useCreateCatalogInvitationCourseBulkMutation, useGetCatalogInvitationsCourseQuery, useLazyPlatformUsersQuery, useLazyPlatformUserGroupsQuery, useGetPersonnalizedSearchQuery, useCreateCatalogInvitationProgramBulkMutation, useGetCatalogInvitationsProgramQuery, useUpdateUserRoleMutation, useUpdateUserStatusMutation, useUpdatePlatformUserRoleWithPoliciesMutation, usePlatformUsersQuery, isPoliciesResponse, platformApiSlice, featureTags, useLazyGetRbacTeamsAccessListQuery, useCreateRbacTeamsAccessMutation, useGetRbacGroupsQuery, usePlatformUserGroupsQuery, useCreateRbacGroupMutation, useUpdateRbacGroupMutation, useDeleteRbacGroupMutation, useCreatePlatformUserGroupMutation, useUpdatePlatformUserGroupMutation, useDeletePlatformUserGroupMutation, useGetRbacGroupDetailsQuery, useGetPlatformUserGroupDetailsQuery, useGetRbacPermissionsMutation, useGetRbacRolesQuery, useCreateRbacRoleMutation, useUpdateRbacRoleMutation, useDeleteRbacRoleMutation, useGetRbacRoleDetailsQuery, useGetRbacActionsDefinitionQuery, useGetRbacResourceDiscoveryQuery, useGetRbacResourceListQuery, useGetRbacPoliciesQuery, useCreateRbacPolicyMutation, useUpdateRbacPolicyMutation, useDeleteRbacPolicyMutation, useGetRbacPolicyDetailsQuery, useGetWatchedGroupsQuery, useCreateWatchedGroupMutation, useUpdateWatchedGroupMutation, useDeleteWatchedGroupMutation, useAddWatchedUserMutation, useRemoveWatchedUserMutation, useAddWatcherMutation, useUpdateWatcherMutation, useDeleteWatcherMutation, useGetWatchedUsersQuery, useGetWatchersQuery, WATCHER_NOTIFICATION_EVENTS, WATCHER_NOTIFICATION_EVENT_LABELS, useGetApplicationFormsQuery, useGetApplicationFormDetailQuery, useCreateApplicationFormMutation, useUpdateApplicationFormMutation, useGetApplicationAdminDetailQuery, useInviteApplicationCandidateMutation, useLazyGetApplicationAttachmentFileQuery, useCreateApplicationWaiverMutation, useDeleteApplicationWaiverMutation, useSubmitApplicationOverrideMutation, useUpdateApplicationPlacementMutation, useDeleteApplicationCourseAssignmentMutation, useCreateApplicationNoteMutation, useUpdateApplicationNoteMutation, useDeleteApplicationNoteMutation, useTransitionApplicationMutation, useLinkApplicationCandidateMutation, useCreateApplicationPlacementsMutation, useGetCustomMentorsQuery, useCreateApplicationCourseAssignmentsMutation, useGetApplicationBlocksQuery, useDeleteApplicationBlockMutation, useGetApplicationsPipelineStatsQuery, useGetApplicationsPipelineQuery, useDeleteApiKeyMutation, useGetApiKeysQuery, useCreateApiKeyMutation, useCreateLLMCredentialMutation, useGetCredentialsSchemaQuery, useGetMaskedLLMCredentialsQuery, useGetLlmsQuery, useDeleteIntegrationCredentialMutation, useDeleteCredentialMutation, useCreateIntegrationCredentialMutation, useGetIntegrationCredentialsSchemaQuery, useGetMaskedIntegrationCredentialsQuery, useGetAccountBillingInfoQuery, useUpdateAutoRechargeInfoMutation, useTriggerAutoRechargeMutation, useCreateStripeCustomerPortalMutation, useSetPlatformConfigurationsMutation, useGetPlatformConfigurationsQuery, useUpdatePlatformMembershipMutation, useGetPlatformMembershipQuery, useGetCustomDomainsQuery, useCreateCustomDomainMutation, useDeleteCustomDomainMutation, useGetStudentMentorCreationStatusQuery, useSetStudentMentorCreationStatusMutation, coreApiSlice, recommendationPromptTypeEnum, useGetRecommendedPromptsListQuery, useCreateRecommendedPromptMutation, useUpdateRecommendedPromptMutation, useDeleteRecommendedPromptMutation, useLazyGetPublicPlatformImageAssetFileUrlQuery, useUpdateTenantMetadataMutation, useCreatePlatformImageAssetMutation, useGetProviderConfigQuery, useCreateProviderConfigMutation, useDeleteProviderConfigMutation, useGetExternalMappingQuery, useGetCredentialsListQuery, useCreateExternalMappingMutation, useDeleteExternalMappingMutation, useGetMemsearchConfigQuery, useUpdateMemsearchConfigMutation, useGetStripeConnectStatusQuery, useStartStripeConnectOnboardingMutation, useLazyGetStripeConnectDashboardQuery, useGetAiSearchMentorsQuery, useListPaywallsQuery, useListPricesQuery, useCreatePriceMutation, useUpdatePriceMutation, useDeletePriceMutation, useGetPaywallConfigQuery, useEnablePaywallMutation, useUpdatePaywallMutation, useLazyGetCourseMetaDataQuery, useLazyGetCourseCompletionOutlinesQuery, useLazyGetCourseEligibilityQuery, useLazyGetEdxSSOTokenQuery, useCreateCourseEnrollmentMutation, useCreateStripeCheckoutSessionMutation, useLazyGetCourseProgressQuery, useLazyGetCourseCompletionQuery, useUpdateExamAttemptMutation, useStartExamMutation, useLazyGetExamInfoQuery, useUpdateUserProjectMutation, useGetTrainingDocumentsQuery, useGetVectorDocumentsQuery, useGetMentorMemoriesListQuery, useGetMemoryCategoriesAdminQuery, useDeleteMentorMemoryMutation, useUpdateMentorMemoryMutation, useCreateMentorMemoryMutation, useLazyGetConnectedServiceAuthUrlQuery, useStarMentorMutation, useUnstarMentorMutation, useCreateUserProjectMutation, useDeleteUserProjectMutation, useGetUserProjectDetailsQuery, useEditTrainingDocumentMutation, useAddTrainingDocumentMutation, useLazyGetCredentialsQuery, useGetMentorSettingsQuery, useEditMentorMutation, useUploadLightLogoMutation, useUploadDarkLogoMutation, useUpdatePlatformInfoMutation, LOGO_ENDPOINTS, useCreateEvalDatasetMutation, useAddEvalDatasetItemsMutation, useUploadEvalDatasetCsvMutation, useDeleteEvalDatasetItemMutation, useListEvalDatasetItemsQuery, evalTotalPages, useListEvalDatasetsQuery, useGetUserProjectsQuery, useCreateSessionIdMutation, useGetMentorCategoriesQuery, useGetTenantChatPrivacyConfigQuery as useGetTenantChatPrivacyConfigQuery$1, useGetCallConfigurationsQuery, useCreateCallConfigurationMutation, useUpdateCallConfigurationMutation, chatPrivacyApiSlice, useDeleteMentorMutation, useForkMentorMutation, useGetToolsQuery, useLazyGetMCPServersQuery, useOauthFindMutation, useLazyStartOAuthFlowQuery, useCreateMCPServerMutation, usePartialUpdateMCPServerMutation, useCreateMCPServerConnectionMutation, usePatchMCPServerConnectionMutation, useGetConnectedServicesQuery, useGetMCPServersQuery, useGetMCPServerConnectionsQuery, useUpdateMCPServerMutation, useDeleteMCPServerMutation, useEditMentorJsonMutation, useDisconnectServiceMutation, useGetPromptCategoriesQuery, PRIVACY_ACTIONS, PRIVACY_ENTITY_TYPES, useGetVoicesQuery, useGetVoiceQuery, useGetMentorGraderConfigurationQuery, useListGraderCriteriaQuery, useCreateMentorGraderConfigurationMutation, useUpdateMentorGraderConfigurationMutation, useCreateGraderCriterionMutation, useUpdateGraderCriterionMutation, useDeleteGraderCriterionMutation, useGetMentorPublicSettingsQuery, useGetChatHistoryFilterQuery, useGetChatHistoryQuery, useGetMentorSummariesQuery, useGetConversationMemoriesQuery, useGetSupportTicketsQuery, useGetSupportTicketMessagesQuery, useCreateSupportTicketMessageMutation, usePatchSupportTicketMutation, useCloseSupportTicketMutation, useCreateLtiMentorMutation, useUpdateLtiMentorMutation, useGetLtiMentorsQuery, useCreateLtiKeyMutation, useUpdateLtiKeyMutation, useDeleteLtiKeyMutation, useGetLtiKeysQuery, useCreateLtiToolMutation, useUpdateLtiToolMutation, useGetLtiToolsQuery, useGetPlatformInfoQuery, useCreatePromptMutation, useGetPromptsSearchQuery, useUpdatePromptMutation, useCreateRedirectTokenMutation, useGetShareableLinkQuery, useCreateShareableLinkMutation, useUpdateShareableLinkMutation, useCreateDisclaimerMutation, useUpdateDisclaimerMutation, useGetDisclaimersQuery, useUpdateRbacMentorAccessMutation, useGetRbacMentorAccessListQuery, useStartEvalRunMutation, useEvaluateEvalRunMutation, useGetEvalRunQuery, useDeleteEvalScoreMutation, useListEvalRunJudgesQuery, useCreateEvalScoreMutation, useDeleteEvalRunMutation, useExportEvalRunMutation, useListEvalRunsQuery, useLazyGetEvalRunQuery, evaluationsApiSlice, EVALUATIONS_TAGS, useGetPersonnalizedMentorsQuery, useCreateCallCredentialsMutation, useGetGuidedPromptsQuery, useUpdateChatSessionSharedMutation, useUpdateMessageFeedbackMutation, useLazyGetPromptsSearchQuery, useLazyGetGuidedPromptsQuery, useGetPublicMentorsQuery, useGetPeriodicAgentsQuery, useGetPeriodicAgentLogsListQuery, useCreatePeriodicAgentMutation, useDeletePeriodicAgentMutation, useDeletePromptMutation, useDeleteTrainingDocumentMutation, useGetTrainingDocumentRetrainScheduleQuery, useCreateTrainingDocumentRetrainScheduleMutation, useCreateMemoryCategoryMutation, useUpdateMemoryCategoryMutation, useDeleteMemoryCategoryMutation, useUpdateArtifactMutation, useLazyGetArtifactVersionQuery, useLazyListArtifactVersionsQuery, useSetCurrentVersionMutation, useListArtifactVersionsQuery, useLazyGetArtifactQuery, useLazyListArtifactsQuery, useEditSessionMutation } from '@iblai/data-layer';
|
|
6
|
-
import { getInitials, useTenantMetadata, WithPermissions, useStripeUpgrade, openExternalUrl, CHAT_AREA_SIZE, isAlphaNumeric32, checkRbacPermission, selectNumberOfActiveChatMessages, useUsername, selectStreaming, isLoggedIn, TOOLS, isSafariBrowser, useShowAttachment, useShowVoiceCall, useShowVoiceRecorder, useMentorSettings, selectShowingSharedChat, selectRbacPermissions, useShowFreeTrialDialog, useEmbedMode, chatInputSliceSelectors, useResponsive, useAccessingPublicRoute, useVisitingTenant, useModelFileUploadCapabilities, useChatFileUpload, useVoiceChat, selectAttachedFiles, MENTOR_CHAT_DOCUMENTS_EXTENSIONS, removeFile, chatInputSliceActions, chatActions, WithFormPermissions, useTenantContext, TimeTracker, advancedTabsProperties, defaultSessionIds, pickWritableFields, ANONYMOUS_USERNAME as ANONYMOUS_USERNAME$3, redirectToAuthSpaJoinTenant, selectActiveTab, useAxdToken, useWelcomeMessage, markdownToPlainText, useCachedSessionId, use402ErrorCheck, selectTokenEnabled, selectToken, useServiceWorker, useUserAgreement, useAdvancedChat, sendMessageToParentWebsite, useMentorTools, useFileDragDrop, eventBus, RemoteEvents, selectEnableChatActionsPopup, advancedTabs, isInIframe, getAuthSpaJoinUrl, addMessage, clearFiles, MENTOR_VISIBILITY } from '@iblai/web-utils';
|
|
5
|
+
import { useGetUserMetadataQuery, useGetUserMetadataEdxQuery, useUpdateUserMetadataMutation, useUpdateUserMetadataEdxMutation, useUploadProfileImageMutation, useResetPasswordMutation, useSelfRetireMutation, useCreateUserInstitutionMutation, useGetUserInstitutionsQuery, useCreateUserEducationMutation, useUpdateUserEducationMutation, useDeleteUserEducationMutation, useGetUserEducationQuery, useCreateUserCompanyMutation, useGetUserCompaniesQuery, useCreateUserExperienceMutation, useUpdateUserExperienceMutation, useDeleteUserExperienceMutation, useGetUserExperienceQuery, useGetUserResumeQuery, useCreateUserResumeMutation, useGetMySubscriptionsQuery, useGetItemSubscriptionQuery, useCancelSubscriptionMutation, useGetLearnerDetailsQuery, useGetUserEnrolledCoursesQuery, useGetUserEnrolledProgramsQuery, useGetUserCatalogPathwaysQuery, useGetUsersAsAssertionsQuery, useGetUserEarnedSkillsQuery, useGetUserReportedSkillsQuery, useGetUserDesiredSkillsQuery, useCreateGlobalMemoryMutation, useGetMemsearchStatusQuery, useGetUserMemorySettingsQuery, useUpdateUserMemorySettingsMutation, useGetGlobalMemoriesQuery, useDeleteGlobalMemoryMutation, useInviteUserMutation, usePlatformInvitationsQuery, useCreateCatalogInvitationCourseBulkMutation, useGetCatalogInvitationsCourseQuery, useLazyPlatformUsersQuery, useLazyPlatformUserGroupsQuery, useGetPersonnalizedSearchQuery, useCreateCatalogInvitationProgramBulkMutation, useGetCatalogInvitationsProgramQuery, useUpdateUserRoleMutation, useUpdateUserStatusMutation, useUpdatePlatformUserRoleWithPoliciesMutation, usePlatformUsersQuery, isPoliciesResponse, platformApiSlice, featureTags, useLazyGetRbacTeamsAccessListQuery, useCreateRbacTeamsAccessMutation, useGetRbacGroupsQuery, usePlatformUserGroupsQuery, useCreateRbacGroupMutation, useUpdateRbacGroupMutation, useDeleteRbacGroupMutation, useCreatePlatformUserGroupMutation, useUpdatePlatformUserGroupMutation, useDeletePlatformUserGroupMutation, useGetRbacGroupDetailsQuery, useGetPlatformUserGroupDetailsQuery, useGetRbacPermissionsMutation, useGetRbacRolesQuery, useCreateRbacRoleMutation, useUpdateRbacRoleMutation, useDeleteRbacRoleMutation, useGetRbacRoleDetailsQuery, useGetRbacActionsDefinitionQuery, useGetRbacResourceDiscoveryQuery, useGetRbacResourceListQuery, useGetRbacPoliciesQuery, useCreateRbacPolicyMutation, useUpdateRbacPolicyMutation, useDeleteRbacPolicyMutation, useGetRbacPolicyDetailsQuery, useGetWatchedGroupsQuery, useCreateWatchedGroupMutation, useUpdateWatchedGroupMutation, useDeleteWatchedGroupMutation, useAddWatchedUserMutation, useRemoveWatchedUserMutation, useAddWatcherMutation, useUpdateWatcherMutation, useDeleteWatcherMutation, useGetWatchedUsersQuery, useGetWatchersQuery, WATCHER_NOTIFICATION_EVENTS, WATCHER_NOTIFICATION_EVENT_LABELS, useGetApplicationFormsQuery, useGetApplicationFormDetailQuery, useCreateApplicationFormMutation, useUpdateApplicationFormMutation, useGetApplicationAdminDetailQuery, useInviteApplicationCandidateMutation, useLazyGetApplicationAttachmentFileQuery, useCreateApplicationWaiverMutation, useDeleteApplicationWaiverMutation, useSubmitApplicationOverrideMutation, useUpdateApplicationPlacementMutation, useDeleteApplicationCourseAssignmentMutation, useCreateApplicationNoteMutation, useUpdateApplicationNoteMutation, useDeleteApplicationNoteMutation, useTransitionApplicationMutation, useLinkApplicationCandidateMutation, useCreateApplicationPlacementsMutation, useGetCustomMentorsQuery, useCreateApplicationCourseAssignmentsMutation, useGetApplicationBlocksQuery, useDeleteApplicationBlockMutation, useGetApplicationsPipelineStatsQuery, useGetApplicationsPipelineQuery, useDeleteApiKeyMutation, useGetApiKeysQuery, useCreateApiKeyMutation, useCreateLLMCredentialMutation, useGetCredentialsSchemaQuery, useGetMaskedLLMCredentialsQuery, useGetLlmsQuery, useDeleteIntegrationCredentialMutation, useDeleteCredentialMutation, useCreateIntegrationCredentialMutation, useGetIntegrationCredentialsSchemaQuery, useGetMaskedIntegrationCredentialsQuery, useGetAccountBillingInfoQuery, useUpdateAutoRechargeInfoMutation, useTriggerAutoRechargeMutation, useCreateStripeCustomerPortalMutation, useSetPlatformConfigurationsMutation, useGetPlatformConfigurationsQuery, useUpdatePlatformMembershipMutation, useGetPlatformMembershipQuery, useGetCustomDomainsQuery, useCreateCustomDomainMutation, useDeleteCustomDomainMutation, useGetStudentMentorCreationStatusQuery, useSetStudentMentorCreationStatusMutation, coreApiSlice, recommendationPromptTypeEnum, useGetRecommendedPromptsListQuery, useCreateRecommendedPromptMutation, useUpdateRecommendedPromptMutation, useDeleteRecommendedPromptMutation, useLazyGetPublicPlatformImageAssetFileUrlQuery, useUpdateTenantMetadataMutation, useCreatePlatformImageAssetMutation, useGetProviderConfigQuery, useCreateProviderConfigMutation, useDeleteProviderConfigMutation, useGetExternalMappingQuery, useGetCredentialsListQuery, useCreateExternalMappingMutation, useDeleteExternalMappingMutation, useGetMemsearchConfigQuery, useUpdateMemsearchConfigMutation, useGetStripeConnectStatusQuery, useStartStripeConnectOnboardingMutation, useLazyGetStripeConnectDashboardQuery, useGetAiSearchMentorsQuery, useListPaywallsQuery, useListPricesQuery, useCreatePriceMutation, useUpdatePriceMutation, useDeletePriceMutation, useGetPaywallConfigQuery, useEnablePaywallMutation, useUpdatePaywallMutation, useLazyGetCourseMetaDataQuery, useLazyGetCourseCompletionOutlinesQuery, useLazyGetCourseEligibilityQuery, useLazyGetEdxSSOTokenQuery, useCreateCourseEnrollmentMutation, useCreateStripeCheckoutSessionMutation, useLazyGetCourseProgressQuery, useLazyGetCourseCompletionQuery, useUpdateExamAttemptMutation, useStartExamMutation, useLazyGetExamInfoQuery, useGetAgentSkillResourcesQuery, useCreateAgentSkillResourceMutation, useUpdateAgentSkillResourceMutation, useUploadAgentSkillResourceAssetMutation, useDeleteAgentSkillResourceMutation, useGetAgentSkillsQuery, useGetMentorSkillAssignmentsQuery, useCreateMentorSkillAssignmentMutation, useUpdateMentorSkillAssignmentMutation, useDeleteMentorSkillAssignmentMutation, useCreateAgentSkillMutation, useUpdateAgentSkillMutation, useDeleteAgentSkillMutation, resolveEffectiveAgentSkills, filterSlashSkills, useUpdateUserProjectMutation, useGetTrainingDocumentsQuery, useGetVectorDocumentsQuery, useGetMentorMemoriesListQuery, useGetMemoryCategoriesAdminQuery, useDeleteMentorMemoryMutation, useUpdateMentorMemoryMutation, useCreateMentorMemoryMutation, useLazyGetConnectedServiceAuthUrlQuery, useStarMentorMutation, useUnstarMentorMutation, useCreateUserProjectMutation, useDeleteUserProjectMutation, useGetUserProjectDetailsQuery, useEditTrainingDocumentMutation, useAddTrainingDocumentMutation, useLazyGetCredentialsQuery, useGetMentorSettingsQuery, useEditMentorMutation, useUploadLightLogoMutation, useUploadDarkLogoMutation, useUpdatePlatformInfoMutation, LOGO_ENDPOINTS, useCreateEvalDatasetMutation, useAddEvalDatasetItemsMutation, useUploadEvalDatasetCsvMutation, useDeleteEvalDatasetItemMutation, useListEvalDatasetItemsQuery, evalTotalPages, useListEvalDatasetsQuery, useGetUserProjectsQuery, useCreateSessionIdMutation, useGetMentorCategoriesQuery, useGetTenantChatPrivacyConfigQuery as useGetTenantChatPrivacyConfigQuery$1, useGetCallConfigurationsQuery, useCreateCallConfigurationMutation, useUpdateCallConfigurationMutation, chatPrivacyApiSlice, useDeleteMentorMutation, useForkMentorMutation, useGetToolsQuery, useLazyGetMCPServersQuery, useOauthFindMutation, useLazyStartOAuthFlowQuery, useCreateMCPServerMutation, usePartialUpdateMCPServerMutation, useCreateMCPServerConnectionMutation, usePatchMCPServerConnectionMutation, useGetConnectedServicesQuery, useGetMCPServersQuery, useGetMCPServerConnectionsQuery, useUpdateMCPServerMutation, useDeleteMCPServerMutation, useEditMentorJsonMutation, useDisconnectServiceMutation, useGetPromptCategoriesQuery, PRIVACY_ACTIONS, PRIVACY_ENTITY_TYPES, useGetVoicesQuery, useGetVoiceQuery, isBaseAgentMentor, useGetMentorGraderConfigurationQuery, useListGraderCriteriaQuery, useCreateMentorGraderConfigurationMutation, useUpdateMentorGraderConfigurationMutation, useCreateGraderCriterionMutation, useUpdateGraderCriterionMutation, useDeleteGraderCriterionMutation, useGetMentorPublicSettingsQuery, useGetChatHistoryFilterQuery, useGetChatHistoryQuery, useGetMentorSummariesQuery, useGetConversationMemoriesQuery, useGetSupportTicketsQuery, useGetSupportTicketMessagesQuery, useCreateSupportTicketMessageMutation, usePatchSupportTicketMutation, useCloseSupportTicketMutation, useCreateLtiMentorMutation, useUpdateLtiMentorMutation, useGetLtiMentorsQuery, useCreateLtiKeyMutation, useUpdateLtiKeyMutation, useDeleteLtiKeyMutation, useGetLtiKeysQuery, useCreateLtiToolMutation, useUpdateLtiToolMutation, useGetLtiToolsQuery, useGetPlatformInfoQuery, useCreatePromptMutation, useGetPromptsSearchQuery, useUpdatePromptMutation, useCreateRedirectTokenMutation, useGetShareableLinkQuery, useCreateShareableLinkMutation, useUpdateShareableLinkMutation, useCreateDisclaimerMutation, useUpdateDisclaimerMutation, useGetDisclaimersQuery, useUpdateRbacMentorAccessMutation, useGetRbacMentorAccessListQuery, useStartEvalRunMutation, useEvaluateEvalRunMutation, useGetEvalRunQuery, useDeleteEvalScoreMutation, useListEvalRunJudgesQuery, useCreateEvalScoreMutation, useDeleteEvalRunMutation, useExportEvalRunMutation, useListEvalRunsQuery, useLazyGetEvalRunQuery, evaluationsApiSlice, EVALUATIONS_TAGS, useGetPersonnalizedMentorsQuery, useCreateCallCredentialsMutation, useGetGuidedPromptsQuery, useUpdateChatSessionSharedMutation, useUpdateMessageFeedbackMutation, useLazyGetPromptsSearchQuery, useLazyGetGuidedPromptsQuery, useGetPublicMentorsQuery, useGetPeriodicAgentsQuery, useGetPeriodicAgentLogsListQuery, useCreatePeriodicAgentMutation, useDeletePeriodicAgentMutation, useDeletePromptMutation, useDeleteTrainingDocumentMutation, useGetTrainingDocumentRetrainScheduleQuery, useCreateTrainingDocumentRetrainScheduleMutation, useCreateMemoryCategoryMutation, useUpdateMemoryCategoryMutation, useDeleteMemoryCategoryMutation, useUpdateArtifactMutation, useLazyGetArtifactVersionQuery, useLazyListArtifactVersionsQuery, useSetCurrentVersionMutation, useListArtifactVersionsQuery, useLazyGetArtifactQuery, useLazyListArtifactsQuery, useEditSessionMutation } from '@iblai/data-layer';
|
|
6
|
+
import { getInitials, useTenantMetadata, WithPermissions, useStripeUpgrade, openExternalUrl, CHAT_AREA_SIZE, isAlphaNumeric32, checkRbacPermission, selectNumberOfActiveChatMessages, useUsername, selectStreaming, isLoggedIn, TOOLS, hasRemoteAiConfig, isSafariBrowser, useShowAttachment, useShowVoiceCall, useShowVoiceRecorder, useMentorSettings, selectShowingSharedChat, selectRbacPermissions, useShowFreeTrialDialog, useEmbedMode, chatInputSliceSelectors, useResponsive, useAccessingPublicRoute, useVisitingTenant, useModelFileUploadCapabilities, useChatFileUpload, useVoiceChat, selectAttachedFiles, MENTOR_CHAT_DOCUMENTS_EXTENSIONS, removeFile, chatInputSliceActions, chatActions, WithFormPermissions, useTenantContext, TimeTracker, advancedTabsProperties, defaultSessionIds, pickWritableFields, ANONYMOUS_USERNAME as ANONYMOUS_USERNAME$3, redirectToAuthSpaJoinTenant, selectActiveTab, useAxdToken, useWelcomeMessage, markdownToPlainText, useCachedSessionId, use402ErrorCheck, selectTokenEnabled, selectToken, useServiceWorker, useUserAgreement, useAdvancedChat, sendMessageToParentWebsite, useMentorTools, useFileDragDrop, eventBus, RemoteEvents, selectEnableChatActionsPopup, advancedTabs, isInIframe, getAuthSpaJoinUrl, addMessage, clearFiles, MENTOR_VISIBILITY } from '@iblai/web-utils';
|
|
7
7
|
import { useDispatch, useSelector } from 'react-redux';
|
|
8
8
|
import { toast } from 'sonner';
|
|
9
9
|
import { useSearchParams, useParams, useRouter, usePathname } from 'next/navigation';
|
|
@@ -98069,118 +98069,6 @@ var gradebookGradebookTab$3 = {
|
|
|
98069
98069
|
previousPage: "Previous",
|
|
98070
98070
|
nextPage: "Next"
|
|
98071
98071
|
};
|
|
98072
|
-
var graderTabLabels$3 = {
|
|
98073
|
-
header: {
|
|
98074
|
-
title: "Grader",
|
|
98075
|
-
description: "Set up how your agent grades work against a rubric you define."
|
|
98076
|
-
},
|
|
98077
|
-
capability: {
|
|
98078
|
-
title: "Grading",
|
|
98079
|
-
description: "Let your agent grade work. When this is on, the agent scores what people submit against the rubric you set up below and shares the result as feedback — great for essays, projects, and practice exercises.",
|
|
98080
|
-
offHint: "Turn it on to write grading instructions and build your rubric. Anything you set up here is kept safe if you later turn it off."
|
|
98081
|
-
},
|
|
98082
|
-
subTabs: {
|
|
98083
|
-
setup: "Grading setup",
|
|
98084
|
-
rubric: "Rubric"
|
|
98085
|
-
},
|
|
98086
|
-
denied: {
|
|
98087
|
-
title: "No access to grading settings",
|
|
98088
|
-
description: "You don't have permission to view this agent's grading setup. Ask an administrator for access."
|
|
98089
|
-
},
|
|
98090
|
-
warnings: {
|
|
98091
|
-
noConfig: "Grading is on but not set up yet — the agent will fail when asked to grade. Save your grading instructions in Grading setup to finish.",
|
|
98092
|
-
noCriteria: "Grading is on but the rubric is empty — the agent will fail when asked to grade. Add at least one criterion in the Rubric tab."
|
|
98093
|
-
},
|
|
98094
|
-
config: {
|
|
98095
|
-
sectionTitle: "Grading setup",
|
|
98096
|
-
gradingMode: {
|
|
98097
|
-
label: "What gets graded",
|
|
98098
|
-
options: {
|
|
98099
|
-
submission: "A submission",
|
|
98100
|
-
conversation: "The conversation"
|
|
98101
|
-
},
|
|
98102
|
-
help: {
|
|
98103
|
-
submission: "The agent grades a piece of work the person hands in, like an essay or answer.",
|
|
98104
|
-
conversation: "The agent grades how the whole conversation went."
|
|
98105
|
-
}
|
|
98106
|
-
},
|
|
98107
|
-
feedbackMode: {
|
|
98108
|
-
label: "Feedback shared with the person",
|
|
98109
|
-
options: {
|
|
98110
|
-
overall: "Overall feedback only",
|
|
98111
|
-
perCriteria: "Feedback per criterion",
|
|
98112
|
-
both: "Overall + per criterion"
|
|
98113
|
-
},
|
|
98114
|
-
help: "The overall score is always calculated — this only controls how much detail is shared back."
|
|
98115
|
-
},
|
|
98116
|
-
instructions: {
|
|
98117
|
-
label: "Grading instructions",
|
|
98118
|
-
placeholder: "Describe what's being graded and anything the grader should know beyond the rubric. E.g. 'You are grading a 500-word persuasive essay on climate policy written by a high-school student. Be encouraging but honest.'",
|
|
98119
|
-
help: "Required. This is the context the agent uses every time it grades."
|
|
98120
|
-
},
|
|
98121
|
-
saveButton: "Save",
|
|
98122
|
-
savingButton: "Saving…"
|
|
98123
|
-
},
|
|
98124
|
-
criteria: {
|
|
98125
|
-
sectionTitle: "Rubric",
|
|
98126
|
-
description: "Each row is one thing the agent looks for and how many points it is worth. The overall score is points earned out of the total.",
|
|
98127
|
-
needsConfigHint: "Save your grading setup first, then add rubric criteria here.",
|
|
98128
|
-
emptyState: "No criteria yet. Add your first one — for example \"Clarity\", 10 points.",
|
|
98129
|
-
addButton: "Add criterion",
|
|
98130
|
-
columns: {
|
|
98131
|
-
name: "Name",
|
|
98132
|
-
criteria: "Criteria",
|
|
98133
|
-
points: "Points"
|
|
98134
|
-
},
|
|
98135
|
-
actionsAria: "Actions for {name}",
|
|
98136
|
-
edit: "Edit",
|
|
98137
|
-
"delete": "Delete",
|
|
98138
|
-
totalPoints: "Total possible points: {total}",
|
|
98139
|
-
scoreHint: "Overall score = points earned ÷ {total}.",
|
|
98140
|
-
lastCriterionHint: "A rubric needs at least one criterion — add another before removing this one.",
|
|
98141
|
-
modal: {
|
|
98142
|
-
addTitle: "Add criterion",
|
|
98143
|
-
editTitle: "Edit criterion",
|
|
98144
|
-
name: {
|
|
98145
|
-
label: "Name",
|
|
98146
|
-
placeholder: "e.g. Clarity",
|
|
98147
|
-
required: "Name is required"
|
|
98148
|
-
},
|
|
98149
|
-
criteria: {
|
|
98150
|
-
label: "Criteria",
|
|
98151
|
-
placeholder: "e.g. The argument is easy to follow and each paragraph makes one clear point.",
|
|
98152
|
-
required: "Criteria is required"
|
|
98153
|
-
},
|
|
98154
|
-
points: {
|
|
98155
|
-
label: "Points",
|
|
98156
|
-
placeholder: "10",
|
|
98157
|
-
positive: "Points must be a positive number"
|
|
98158
|
-
},
|
|
98159
|
-
save: "Save",
|
|
98160
|
-
saving: "Saving…",
|
|
98161
|
-
cancel: "Cancel"
|
|
98162
|
-
},
|
|
98163
|
-
deleteModal: {
|
|
98164
|
-
title: "Delete criterion",
|
|
98165
|
-
confirmationPrefix: "Are you sure you want to remove",
|
|
98166
|
-
confirmationSuffix: " from the rubric?",
|
|
98167
|
-
cancel: "Cancel",
|
|
98168
|
-
"delete": "Delete",
|
|
98169
|
-
deleting: "Deleting…"
|
|
98170
|
-
}
|
|
98171
|
-
},
|
|
98172
|
-
toasts: {
|
|
98173
|
-
toggleOn: "Grading turned on",
|
|
98174
|
-
toggleOff: "Grading turned off — your rubric is kept for next time",
|
|
98175
|
-
toggleError: "Couldn't update grading",
|
|
98176
|
-
configSaved: "Grading setup saved",
|
|
98177
|
-
configError: "Couldn't save grading setup",
|
|
98178
|
-
criterionAdded: "Criterion added",
|
|
98179
|
-
criterionUpdated: "Criterion updated",
|
|
98180
|
-
criterionDeleted: "Criterion deleted",
|
|
98181
|
-
criterionError: "Couldn't update the rubric"
|
|
98182
|
-
}
|
|
98183
|
-
};
|
|
98184
98072
|
var careerExperienceDialog$3 = {
|
|
98185
98073
|
pleaseSelectACompany: "Please select a company",
|
|
98186
98074
|
endDateCannotBeBeforeStartDate: "End date cannot be before start date",
|
|
@@ -98334,6 +98222,9 @@ var chatInputFormInsideButtons$3 = {
|
|
|
98334
98222
|
studyMode: "Study Mode",
|
|
98335
98223
|
deepResearch: "Deep Research",
|
|
98336
98224
|
memory: "Memory",
|
|
98225
|
+
cowork: "Cowork",
|
|
98226
|
+
coworkNeedsBackend: "Enable a large local model or sign in to a workspace to use Cowork.",
|
|
98227
|
+
coworkModelTooSmall: "Your local model is too small for Cowork. Pick a model of at least 14GB in Local Models.",
|
|
98337
98228
|
moreOptions: "More options"
|
|
98338
98229
|
};
|
|
98339
98230
|
var chatInputFormMemoryMenu$3 = {
|
|
@@ -98491,7 +98382,57 @@ var clawSandboxAgentSkills$3 = {
|
|
|
98491
98382
|
fieldVersionPlaceholder: "e.g. 1.0.0",
|
|
98492
98383
|
fieldDescription: "Description",
|
|
98493
98384
|
fieldDescriptionPlaceholder: "e.g. Search the web for information",
|
|
98494
|
-
fieldInstruction: "Instruction"
|
|
98385
|
+
fieldInstruction: "Instruction",
|
|
98386
|
+
sessionNote: "Skills added or removed here apply to new chat sessions only. Edits to a skill's instructions apply immediately, including in conversations already in progress.",
|
|
98387
|
+
effectiveHeading: "This agent's skills",
|
|
98388
|
+
catalogHeading: "Available skills",
|
|
98389
|
+
noEffectiveSkills: "No skills enabled for this agent yet. Add one from the available skills below.",
|
|
98390
|
+
addToAgent: "Add",
|
|
98391
|
+
addToAgentLabel: "Add {name} to this agent",
|
|
98392
|
+
removeFromAgent: "Remove from agent",
|
|
98393
|
+
skillAdded: "{name} added",
|
|
98394
|
+
skillRemoved: "{name} removed",
|
|
98395
|
+
featuredBadge: "Featured",
|
|
98396
|
+
nativeBadge: "Native",
|
|
98397
|
+
privateBadge: "Only this agent",
|
|
98398
|
+
fieldCategory: "Category",
|
|
98399
|
+
fieldCategoryPlaceholder: "e.g. web, code, data",
|
|
98400
|
+
privateToAgent: "Only this agent",
|
|
98401
|
+
privateToAgentHint: "Private skills are available to this agent only and take precedence over platform skills with the same slug.",
|
|
98402
|
+
instructionHint: "The playbook the agent follows when the skill is used. Edits apply immediately, including in conversations already in progress.",
|
|
98403
|
+
filesHint: "Optional resources the agent can use with this skill. References and scripts are text files; assets are uploaded files.",
|
|
98404
|
+
filesAfterCreateHint: "You can attach resources to this skill after creating it (reopen it with Edit).",
|
|
98405
|
+
noFiles: "No resources attached yet.",
|
|
98406
|
+
loadingFiles: "Loading resources...",
|
|
98407
|
+
fileTypeLabel: "Type",
|
|
98408
|
+
fileTypeReference: "Reference",
|
|
98409
|
+
fileTypeScript: "Script",
|
|
98410
|
+
fileTypeAsset: "Asset",
|
|
98411
|
+
fileNameLabel: "File name",
|
|
98412
|
+
fileNamePlaceholder: "e.g. rubric.md",
|
|
98413
|
+
fileContentLabel: "Content",
|
|
98414
|
+
fileContentPlaceholder: "The file's text content",
|
|
98415
|
+
addFileButton: "Add resource",
|
|
98416
|
+
adding: "Adding...",
|
|
98417
|
+
uploading: "Uploading...",
|
|
98418
|
+
fileAdded: "Resource added",
|
|
98419
|
+
fileUploaded: "Resource uploaded",
|
|
98420
|
+
fileSaved: "Resource saved",
|
|
98421
|
+
fileDeleted: "Resource deleted",
|
|
98422
|
+
failedToSaveFile: "Failed to save resource",
|
|
98423
|
+
failedToUploadFile: "Failed to upload resource",
|
|
98424
|
+
failedToDeleteFile: "Failed to delete resource",
|
|
98425
|
+
detailsTab: "General",
|
|
98426
|
+
filesTab: "Resources",
|
|
98427
|
+
newFile: "New Resource",
|
|
98428
|
+
newFileDialogTitle: "New Resource",
|
|
98429
|
+
editFileDialogTitle: "Edit Resource",
|
|
98430
|
+
deleteFileDialogTitle: "Delete Resource",
|
|
98431
|
+
deleteFileConfirmation: "Are you sure you want to delete {name}? This action cannot be undone.",
|
|
98432
|
+
chooseFile: "Choose file",
|
|
98433
|
+
upload: "Upload",
|
|
98434
|
+
download: "Download",
|
|
98435
|
+
resourcesItemLabel: "resources"
|
|
98495
98436
|
};
|
|
98496
98437
|
var clawSandboxHelpers$3 = {
|
|
98497
98438
|
unknown: "Unknown",
|
|
@@ -100756,7 +100697,7 @@ var safetyTabLabels$3 = {
|
|
|
100756
100697
|
};
|
|
100757
100698
|
var screenshareTabLabels$3 = {
|
|
100758
100699
|
header: {
|
|
100759
|
-
title: "Screen
|
|
100700
|
+
title: "Screen",
|
|
100760
100701
|
description: "How your agent behaves when a user shares their screen during a voice call."
|
|
100761
100702
|
},
|
|
100762
100703
|
capability: {
|
|
@@ -102395,6 +102336,19 @@ var platformNavbar$3 = {
|
|
|
102395
102336
|
placementExamsHeader: "Placement exams",
|
|
102396
102337
|
placementExamFallback: "Placement exam"
|
|
102397
102338
|
};
|
|
102339
|
+
var slashSkillPicker$3 = {
|
|
102340
|
+
listLabel: "Agent skills",
|
|
102341
|
+
resultsAnnouncement: "{count} skills available. Use arrow keys to browse and Enter to select.",
|
|
102342
|
+
loading: "Loading..."
|
|
102343
|
+
};
|
|
102344
|
+
var skillsTabLabels$3 = {
|
|
102345
|
+
header: {
|
|
102346
|
+
title: "Skills",
|
|
102347
|
+
description: "Reusable playbooks you can attach to this agent — each one is a set of instructions for a job. In chat, type / to use one."
|
|
102348
|
+
},
|
|
102349
|
+
notBaseAgent: "Skills are only available to Base Agents.",
|
|
102350
|
+
loading: "Loading..."
|
|
102351
|
+
};
|
|
102398
102352
|
var placementExam$3 = {
|
|
102399
102353
|
title: "Placement exam",
|
|
102400
102354
|
back: "Back"
|
|
@@ -102691,6 +102645,118 @@ var profileApplicationsQuestionsEditor$3 = {
|
|
|
102691
102645
|
collapseSection: "Collapse section",
|
|
102692
102646
|
expandSection: "Expand section"
|
|
102693
102647
|
};
|
|
102648
|
+
var graderTabLabels$3 = {
|
|
102649
|
+
header: {
|
|
102650
|
+
title: "Grader",
|
|
102651
|
+
description: "Set up how your agent grades work against a rubric you define."
|
|
102652
|
+
},
|
|
102653
|
+
capability: {
|
|
102654
|
+
title: "Grading",
|
|
102655
|
+
description: "Let your agent grade work. When this is on, the agent scores what people submit against the rubric you set up below and shares the result as feedback — great for essays, projects, and practice exercises.",
|
|
102656
|
+
offHint: "Turn it on to write grading instructions and build your rubric. Anything you set up here is kept safe if you later turn it off."
|
|
102657
|
+
},
|
|
102658
|
+
subTabs: {
|
|
102659
|
+
setup: "Grading setup",
|
|
102660
|
+
rubric: "Rubric"
|
|
102661
|
+
},
|
|
102662
|
+
denied: {
|
|
102663
|
+
title: "No access to grading settings",
|
|
102664
|
+
description: "You don't have permission to view this agent's grading setup. Ask an administrator for access."
|
|
102665
|
+
},
|
|
102666
|
+
warnings: {
|
|
102667
|
+
noConfig: "Grading is on but not set up yet — the agent will fail when asked to grade. Save your grading instructions in Grading setup to finish.",
|
|
102668
|
+
noCriteria: "Grading is on but the rubric is empty — the agent will fail when asked to grade. Add at least one criterion in the Rubric tab."
|
|
102669
|
+
},
|
|
102670
|
+
config: {
|
|
102671
|
+
sectionTitle: "Grading setup",
|
|
102672
|
+
gradingMode: {
|
|
102673
|
+
label: "What gets graded",
|
|
102674
|
+
options: {
|
|
102675
|
+
submission: "A submission",
|
|
102676
|
+
conversation: "The conversation"
|
|
102677
|
+
},
|
|
102678
|
+
help: {
|
|
102679
|
+
submission: "The agent grades a piece of work the person hands in, like an essay or answer.",
|
|
102680
|
+
conversation: "The agent grades how the whole conversation went."
|
|
102681
|
+
}
|
|
102682
|
+
},
|
|
102683
|
+
feedbackMode: {
|
|
102684
|
+
label: "Feedback shared with the person",
|
|
102685
|
+
options: {
|
|
102686
|
+
overall: "Overall feedback only",
|
|
102687
|
+
perCriteria: "Feedback per criterion",
|
|
102688
|
+
both: "Overall + per criterion"
|
|
102689
|
+
},
|
|
102690
|
+
help: "The overall score is always calculated — this only controls how much detail is shared back."
|
|
102691
|
+
},
|
|
102692
|
+
instructions: {
|
|
102693
|
+
label: "Grading instructions",
|
|
102694
|
+
placeholder: "Describe what's being graded and anything the grader should know beyond the rubric. E.g. 'You are grading a 500-word persuasive essay on climate policy written by a high-school student. Be encouraging but honest.'",
|
|
102695
|
+
help: "Required. This is the context the agent uses every time it grades."
|
|
102696
|
+
},
|
|
102697
|
+
saveButton: "Save",
|
|
102698
|
+
savingButton: "Saving…"
|
|
102699
|
+
},
|
|
102700
|
+
criteria: {
|
|
102701
|
+
sectionTitle: "Rubric",
|
|
102702
|
+
description: "Each row is one thing the agent looks for and how many points it is worth. The overall score is points earned out of the total.",
|
|
102703
|
+
needsConfigHint: "Save your grading setup first, then add rubric criteria here.",
|
|
102704
|
+
emptyState: "No criteria yet. Add your first one — for example \"Clarity\", 10 points.",
|
|
102705
|
+
addButton: "Add criterion",
|
|
102706
|
+
columns: {
|
|
102707
|
+
name: "Name",
|
|
102708
|
+
criteria: "Criteria",
|
|
102709
|
+
points: "Points"
|
|
102710
|
+
},
|
|
102711
|
+
actionsAria: "Actions for {name}",
|
|
102712
|
+
edit: "Edit",
|
|
102713
|
+
"delete": "Delete",
|
|
102714
|
+
totalPoints: "Total possible points: {total}",
|
|
102715
|
+
scoreHint: "Overall score = points earned ÷ {total}.",
|
|
102716
|
+
lastCriterionHint: "A rubric needs at least one criterion — add another before removing this one.",
|
|
102717
|
+
modal: {
|
|
102718
|
+
addTitle: "Add criterion",
|
|
102719
|
+
editTitle: "Edit criterion",
|
|
102720
|
+
name: {
|
|
102721
|
+
label: "Name",
|
|
102722
|
+
placeholder: "e.g. Clarity",
|
|
102723
|
+
required: "Name is required"
|
|
102724
|
+
},
|
|
102725
|
+
criteria: {
|
|
102726
|
+
label: "Criteria",
|
|
102727
|
+
placeholder: "e.g. The argument is easy to follow and each paragraph makes one clear point.",
|
|
102728
|
+
required: "Criteria is required"
|
|
102729
|
+
},
|
|
102730
|
+
points: {
|
|
102731
|
+
label: "Points",
|
|
102732
|
+
placeholder: "10",
|
|
102733
|
+
positive: "Points must be a positive number"
|
|
102734
|
+
},
|
|
102735
|
+
save: "Save",
|
|
102736
|
+
saving: "Saving…",
|
|
102737
|
+
cancel: "Cancel"
|
|
102738
|
+
},
|
|
102739
|
+
deleteModal: {
|
|
102740
|
+
title: "Delete criterion",
|
|
102741
|
+
confirmationPrefix: "Are you sure you want to remove",
|
|
102742
|
+
confirmationSuffix: " from the rubric?",
|
|
102743
|
+
cancel: "Cancel",
|
|
102744
|
+
"delete": "Delete",
|
|
102745
|
+
deleting: "Deleting…"
|
|
102746
|
+
}
|
|
102747
|
+
},
|
|
102748
|
+
toasts: {
|
|
102749
|
+
toggleOn: "Grading turned on",
|
|
102750
|
+
toggleOff: "Grading turned off — your rubric is kept for next time",
|
|
102751
|
+
toggleError: "Couldn't update grading",
|
|
102752
|
+
configSaved: "Grading setup saved",
|
|
102753
|
+
configError: "Couldn't save grading setup",
|
|
102754
|
+
criterionAdded: "Criterion added",
|
|
102755
|
+
criterionUpdated: "Criterion updated",
|
|
102756
|
+
criterionDeleted: "Criterion deleted",
|
|
102757
|
+
criterionError: "Couldn't update the rubric"
|
|
102758
|
+
}
|
|
102759
|
+
};
|
|
102694
102760
|
var en = {
|
|
102695
102761
|
accessTabAddAccess: accessTabAddAccess$3,
|
|
102696
102762
|
accessTabLabels: accessTabLabels$3,
|
|
@@ -102745,7 +102811,6 @@ var en = {
|
|
|
102745
102811
|
careerEducationDialog: careerEducationDialog$3,
|
|
102746
102812
|
careerEducationTab: careerEducationTab$3,
|
|
102747
102813
|
gradebookGradebookTab: gradebookGradebookTab$3,
|
|
102748
|
-
graderTabLabels: graderTabLabels$3,
|
|
102749
102814
|
careerExperienceDialog: careerExperienceDialog$3,
|
|
102750
102815
|
careerExperienceTab: careerExperienceTab$3,
|
|
102751
102816
|
careerInstitutionDialog: careerInstitutionDialog$3,
|
|
@@ -102939,10 +103004,13 @@ var en = {
|
|
|
102939
103004
|
benchmarksAddItemsModal: benchmarksAddItemsModal$3,
|
|
102940
103005
|
platformSidebar: platformSidebar$3,
|
|
102941
103006
|
platformNavbar: platformNavbar$3,
|
|
103007
|
+
slashSkillPicker: slashSkillPicker$3,
|
|
103008
|
+
skillsTabLabels: skillsTabLabels$3,
|
|
102942
103009
|
placementExam: placementExam$3,
|
|
102943
103010
|
applyApplyWizard: applyApplyWizard$3,
|
|
102944
103011
|
profileApplicationsTab: profileApplicationsTab$3,
|
|
102945
|
-
profileApplicationsQuestionsEditor: profileApplicationsQuestionsEditor$3
|
|
103012
|
+
profileApplicationsQuestionsEditor: profileApplicationsQuestionsEditor$3,
|
|
103013
|
+
graderTabLabels: graderTabLabels$3
|
|
102946
103014
|
};
|
|
102947
103015
|
|
|
102948
103016
|
var accessTabAddAccess$2 = {
|
|
@@ -104452,6 +104520,9 @@ var chatInputFormInsideButtons$2 = {
|
|
|
104452
104520
|
studyMode: "Mode Étude",
|
|
104453
104521
|
deepResearch: "Recherche Approfondie",
|
|
104454
104522
|
memory: "Mémoire",
|
|
104523
|
+
cowork: "Cowork",
|
|
104524
|
+
coworkNeedsBackend: "Activez un grand modèle local ou connectez-vous à un espace de travail pour utiliser Cowork.",
|
|
104525
|
+
coworkModelTooSmall: "Votre modèle local est trop petit pour Cowork. Choisissez un modèle d’au moins 14 Go dans Modèles Locaux.",
|
|
104455
104526
|
moreOptions: "Plus d'options"
|
|
104456
104527
|
};
|
|
104457
104528
|
var chatInputFormMemoryMenu$2 = {
|
|
@@ -104609,7 +104680,57 @@ var clawSandboxAgentSkills$2 = {
|
|
|
104609
104680
|
fieldVersionPlaceholder: "ex. 1.0.0",
|
|
104610
104681
|
fieldDescription: "Description",
|
|
104611
104682
|
fieldDescriptionPlaceholder: "ex. Rechercher des informations sur le web",
|
|
104612
|
-
fieldInstruction: "Instruction"
|
|
104683
|
+
fieldInstruction: "Instruction",
|
|
104684
|
+
sessionNote: "Les compétences ajoutées ou supprimées ici ne s'appliquent qu'aux nouvelles sessions de chat. Les modifications des instructions d'une compétence s'appliquent immédiatement, y compris dans les conversations en cours.",
|
|
104685
|
+
effectiveHeading: "Compétences de cet agent",
|
|
104686
|
+
catalogHeading: "Compétences disponibles",
|
|
104687
|
+
noEffectiveSkills: "Cet agent n'a pas encore de compétences activées. Ajoutez-en une depuis les compétences disponibles.",
|
|
104688
|
+
addToAgent: "Ajouter",
|
|
104689
|
+
addToAgentLabel: "Ajouter {name} à cet agent",
|
|
104690
|
+
removeFromAgent: "Retirer de l'agent",
|
|
104691
|
+
skillAdded: "{name} ajoutée",
|
|
104692
|
+
skillRemoved: "{name} retirée",
|
|
104693
|
+
featuredBadge: "En vedette",
|
|
104694
|
+
nativeBadge: "Native",
|
|
104695
|
+
privateBadge: "Cet agent uniquement",
|
|
104696
|
+
fieldCategory: "Catégorie",
|
|
104697
|
+
fieldCategoryPlaceholder: "p. ex. web, code, données",
|
|
104698
|
+
privateToAgent: "Cet agent uniquement",
|
|
104699
|
+
privateToAgentHint: "Les compétences privées ne sont disponibles que pour cet agent et priment sur les compétences de la plateforme portant le même slug.",
|
|
104700
|
+
instructionHint: "Le guide que l'agent suit lorsque la compétence est utilisée. Les modifications s'appliquent immédiatement, y compris dans les conversations en cours.",
|
|
104701
|
+
filesHint: "Ressources facultatives que l'agent peut utiliser avec cette compétence. Les références et les scripts sont des fichiers texte ; les assets sont des fichiers téléversés.",
|
|
104702
|
+
filesAfterCreateHint: "Vous pouvez joindre des ressources à cette compétence après sa création (rouvrez-la avec Modifier).",
|
|
104703
|
+
noFiles: "Aucune ressource jointe pour le moment.",
|
|
104704
|
+
loadingFiles: "Chargement des ressources...",
|
|
104705
|
+
fileTypeLabel: "Type",
|
|
104706
|
+
fileTypeReference: "Référence",
|
|
104707
|
+
fileTypeScript: "Script",
|
|
104708
|
+
fileTypeAsset: "Ressource",
|
|
104709
|
+
fileNameLabel: "Nom du fichier",
|
|
104710
|
+
fileNamePlaceholder: "p. ex. grille.md",
|
|
104711
|
+
fileContentLabel: "Contenu",
|
|
104712
|
+
fileContentPlaceholder: "Le contenu texte du fichier",
|
|
104713
|
+
addFileButton: "Ajouter la ressource",
|
|
104714
|
+
adding: "Ajout...",
|
|
104715
|
+
uploading: "Téléversement...",
|
|
104716
|
+
fileAdded: "Ressource ajoutée",
|
|
104717
|
+
fileUploaded: "Ressource téléversée",
|
|
104718
|
+
fileSaved: "Ressource enregistrée",
|
|
104719
|
+
fileDeleted: "Ressource supprimée",
|
|
104720
|
+
failedToSaveFile: "Impossible d'enregistrer la ressource",
|
|
104721
|
+
failedToUploadFile: "Impossible de téléverser la ressource",
|
|
104722
|
+
failedToDeleteFile: "Impossible de supprimer la ressource",
|
|
104723
|
+
detailsTab: "Général",
|
|
104724
|
+
filesTab: "Ressources",
|
|
104725
|
+
newFile: "Nouvelle ressource",
|
|
104726
|
+
newFileDialogTitle: "Nouvelle ressource",
|
|
104727
|
+
editFileDialogTitle: "Modifier la ressource",
|
|
104728
|
+
deleteFileDialogTitle: "Supprimer la ressource",
|
|
104729
|
+
deleteFileConfirmation: "Voulez-vous vraiment supprimer {name} ? Cette action est irréversible.",
|
|
104730
|
+
chooseFile: "Choisir un fichier",
|
|
104731
|
+
upload: "Téléverser",
|
|
104732
|
+
download: "Télécharger",
|
|
104733
|
+
resourcesItemLabel: "ressources"
|
|
104613
104734
|
};
|
|
104614
104735
|
var clawSandboxHelpers$2 = {
|
|
104615
104736
|
unknown: "Inconnu",
|
|
@@ -106874,7 +106995,7 @@ var safetyTabLabels$2 = {
|
|
|
106874
106995
|
};
|
|
106875
106996
|
var screenshareTabLabels$2 = {
|
|
106876
106997
|
header: {
|
|
106877
|
-
title: "
|
|
106998
|
+
title: "Écran",
|
|
106878
106999
|
description: "Comment votre agent se comporte lorsqu’un utilisateur partage son écran pendant un appel vocal."
|
|
106879
107000
|
},
|
|
106880
107001
|
capability: {
|
|
@@ -108809,6 +108930,19 @@ var profileApplicationsQuestionsEditor$2 = {
|
|
|
108809
108930
|
collapseSection: "Réduire la section",
|
|
108810
108931
|
expandSection: "Développer la section"
|
|
108811
108932
|
};
|
|
108933
|
+
var slashSkillPicker$2 = {
|
|
108934
|
+
listLabel: "Compétences de l'agent",
|
|
108935
|
+
resultsAnnouncement: "{count} compétences disponibles. Utilisez les flèches pour parcourir et Entrée pour sélectionner.",
|
|
108936
|
+
loading: "Chargement..."
|
|
108937
|
+
};
|
|
108938
|
+
var skillsTabLabels$2 = {
|
|
108939
|
+
header: {
|
|
108940
|
+
title: "Compétences",
|
|
108941
|
+
description: "Des guides réutilisables à attacher à cet agent — chacun est un ensemble d'instructions pour une tâche. Dans le chat, tapez / pour en utiliser un."
|
|
108942
|
+
},
|
|
108943
|
+
notBaseAgent: "Les compétences ne sont disponibles que pour les agents de base.",
|
|
108944
|
+
loading: "Chargement..."
|
|
108945
|
+
};
|
|
108812
108946
|
var fr = {
|
|
108813
108947
|
accessTabAddAccess: accessTabAddAccess$2,
|
|
108814
108948
|
accessTabLabels: accessTabLabels$2,
|
|
@@ -109060,7 +109194,9 @@ var fr = {
|
|
|
109060
109194
|
placementExam: placementExam$2,
|
|
109061
109195
|
applyApplyWizard: applyApplyWizard$2,
|
|
109062
109196
|
profileApplicationsTab: profileApplicationsTab$2,
|
|
109063
|
-
profileApplicationsQuestionsEditor: profileApplicationsQuestionsEditor$2
|
|
109197
|
+
profileApplicationsQuestionsEditor: profileApplicationsQuestionsEditor$2,
|
|
109198
|
+
slashSkillPicker: slashSkillPicker$2,
|
|
109199
|
+
skillsTabLabels: skillsTabLabels$2
|
|
109064
109200
|
};
|
|
109065
109201
|
|
|
109066
109202
|
var accessTabAddAccess$1 = {
|
|
@@ -110570,6 +110706,9 @@ var chatInputFormInsideButtons$1 = {
|
|
|
110570
110706
|
studyMode: "Modo Estudio",
|
|
110571
110707
|
deepResearch: "Investigación Profunda",
|
|
110572
110708
|
memory: "Memoria",
|
|
110709
|
+
cowork: "Cowork",
|
|
110710
|
+
coworkNeedsBackend: "Activa un modelo local grande o inicia sesión en un espacio de trabajo para usar Cowork.",
|
|
110711
|
+
coworkModelTooSmall: "Tu modelo local es demasiado pequeño para Cowork. Elige un modelo de al menos 14 GB en Modelos Locales.",
|
|
110573
110712
|
moreOptions: "Más opciones"
|
|
110574
110713
|
};
|
|
110575
110714
|
var chatInputFormMemoryMenu$1 = {
|
|
@@ -110727,7 +110866,57 @@ var clawSandboxAgentSkills$1 = {
|
|
|
110727
110866
|
fieldVersionPlaceholder: "ej. 1.0.0",
|
|
110728
110867
|
fieldDescription: "Descripción",
|
|
110729
110868
|
fieldDescriptionPlaceholder: "ej. Buscar información en la web",
|
|
110730
|
-
fieldInstruction: "Instrucción"
|
|
110869
|
+
fieldInstruction: "Instrucción",
|
|
110870
|
+
sessionNote: "Las habilidades añadidas o eliminadas aquí solo se aplican a las nuevas sesiones de chat. Los cambios en las instrucciones de una habilidad se aplican de inmediato, incluso en conversaciones en curso.",
|
|
110871
|
+
effectiveHeading: "Habilidades de este agente",
|
|
110872
|
+
catalogHeading: "Habilidades disponibles",
|
|
110873
|
+
noEffectiveSkills: "Este agente aún no tiene habilidades habilitadas. Añade una desde las habilidades disponibles.",
|
|
110874
|
+
addToAgent: "Añadir",
|
|
110875
|
+
addToAgentLabel: "Añadir {name} a este agente",
|
|
110876
|
+
removeFromAgent: "Quitar del agente",
|
|
110877
|
+
skillAdded: "{name} añadida",
|
|
110878
|
+
skillRemoved: "{name} eliminada",
|
|
110879
|
+
featuredBadge: "Destacada",
|
|
110880
|
+
nativeBadge: "Nativa",
|
|
110881
|
+
privateBadge: "Solo este agente",
|
|
110882
|
+
fieldCategory: "Categoría",
|
|
110883
|
+
fieldCategoryPlaceholder: "p. ej. web, código, datos",
|
|
110884
|
+
privateToAgent: "Solo este agente",
|
|
110885
|
+
privateToAgentHint: "Las habilidades privadas solo están disponibles para este agente y tienen prioridad sobre las habilidades de la plataforma con el mismo slug.",
|
|
110886
|
+
instructionHint: "La guía que sigue el agente cuando se usa la habilidad. Los cambios se aplican de inmediato, incluso en conversaciones en curso.",
|
|
110887
|
+
filesHint: "Recursos opcionales que el agente puede usar con esta habilidad. Las referencias y los scripts son archivos de texto; los assets son archivos subidos.",
|
|
110888
|
+
filesAfterCreateHint: "Puedes adjuntar recursos a esta habilidad después de crearla (vuelve a abrirla con Editar).",
|
|
110889
|
+
noFiles: "Aún no hay recursos adjuntos.",
|
|
110890
|
+
loadingFiles: "Cargando recursos...",
|
|
110891
|
+
fileTypeLabel: "Tipo",
|
|
110892
|
+
fileTypeReference: "Referencia",
|
|
110893
|
+
fileTypeScript: "Script",
|
|
110894
|
+
fileTypeAsset: "Recurso",
|
|
110895
|
+
fileNameLabel: "Nombre del archivo",
|
|
110896
|
+
fileNamePlaceholder: "p. ej. rubrica.md",
|
|
110897
|
+
fileContentLabel: "Contenido",
|
|
110898
|
+
fileContentPlaceholder: "El contenido de texto del archivo",
|
|
110899
|
+
addFileButton: "Añadir recurso",
|
|
110900
|
+
adding: "Añadiendo...",
|
|
110901
|
+
uploading: "Subiendo...",
|
|
110902
|
+
fileAdded: "Recurso añadido",
|
|
110903
|
+
fileUploaded: "Recurso subido",
|
|
110904
|
+
fileSaved: "Recurso guardado",
|
|
110905
|
+
fileDeleted: "Recurso eliminado",
|
|
110906
|
+
failedToSaveFile: "No se pudo guardar el recurso",
|
|
110907
|
+
failedToUploadFile: "No se pudo subir el recurso",
|
|
110908
|
+
failedToDeleteFile: "No se pudo eliminar el recurso",
|
|
110909
|
+
detailsTab: "General",
|
|
110910
|
+
filesTab: "Recursos",
|
|
110911
|
+
newFile: "Nuevo recurso",
|
|
110912
|
+
newFileDialogTitle: "Nuevo recurso",
|
|
110913
|
+
editFileDialogTitle: "Editar recurso",
|
|
110914
|
+
deleteFileDialogTitle: "Eliminar recurso",
|
|
110915
|
+
deleteFileConfirmation: "¿Seguro que quieres eliminar {name}? Esta acción no se puede deshacer.",
|
|
110916
|
+
chooseFile: "Elegir archivo",
|
|
110917
|
+
upload: "Subir",
|
|
110918
|
+
download: "Descargar",
|
|
110919
|
+
resourcesItemLabel: "recursos"
|
|
110731
110920
|
};
|
|
110732
110921
|
var clawSandboxHelpers$1 = {
|
|
110733
110922
|
unknown: "Desconocido",
|
|
@@ -112992,7 +113181,7 @@ var safetyTabLabels$1 = {
|
|
|
112992
113181
|
};
|
|
112993
113182
|
var screenshareTabLabels$1 = {
|
|
112994
113183
|
header: {
|
|
112995
|
-
title: "Pantalla
|
|
113184
|
+
title: "Pantalla",
|
|
112996
113185
|
description: "Cómo se comporta tu agente cuando un usuario comparte su pantalla durante una llamada de voz."
|
|
112997
113186
|
},
|
|
112998
113187
|
capability: {
|
|
@@ -114927,6 +115116,19 @@ var profileApplicationsQuestionsEditor$1 = {
|
|
|
114927
115116
|
collapseSection: "Contraer sección",
|
|
114928
115117
|
expandSection: "Expandir sección"
|
|
114929
115118
|
};
|
|
115119
|
+
var slashSkillPicker$1 = {
|
|
115120
|
+
listLabel: "Habilidades del agente",
|
|
115121
|
+
resultsAnnouncement: "{count} habilidades disponibles. Usa las flechas para navegar y Enter para seleccionar.",
|
|
115122
|
+
loading: "Cargando..."
|
|
115123
|
+
};
|
|
115124
|
+
var skillsTabLabels$1 = {
|
|
115125
|
+
header: {
|
|
115126
|
+
title: "Habilidades",
|
|
115127
|
+
description: "Guías reutilizables que puedes adjuntar a este agente: cada una es un conjunto de instrucciones para una tarea. En el chat, escribe / para usar una."
|
|
115128
|
+
},
|
|
115129
|
+
notBaseAgent: "Las habilidades solo están disponibles para los agentes base.",
|
|
115130
|
+
loading: "Cargando..."
|
|
115131
|
+
};
|
|
114930
115132
|
var es = {
|
|
114931
115133
|
accessTabAddAccess: accessTabAddAccess$1,
|
|
114932
115134
|
accessTabLabels: accessTabLabels$1,
|
|
@@ -115178,7 +115380,9 @@ var es = {
|
|
|
115178
115380
|
placementExam: placementExam$1,
|
|
115179
115381
|
applyApplyWizard: applyApplyWizard$1,
|
|
115180
115382
|
profileApplicationsTab: profileApplicationsTab$1,
|
|
115181
|
-
profileApplicationsQuestionsEditor: profileApplicationsQuestionsEditor$1
|
|
115383
|
+
profileApplicationsQuestionsEditor: profileApplicationsQuestionsEditor$1,
|
|
115384
|
+
slashSkillPicker: slashSkillPicker$1,
|
|
115385
|
+
skillsTabLabels: skillsTabLabels$1
|
|
115182
115386
|
};
|
|
115183
115387
|
|
|
115184
115388
|
var accessTabAddAccess = {
|
|
@@ -116688,6 +116892,9 @@ var chatInputFormInsideButtons = {
|
|
|
116688
116892
|
studyMode: "学习模式",
|
|
116689
116893
|
deepResearch: "深度研究",
|
|
116690
116894
|
memory: "记忆",
|
|
116895
|
+
cowork: "Cowork",
|
|
116896
|
+
coworkNeedsBackend: "启用大型本地模型或登录工作区即可使用 Cowork。",
|
|
116897
|
+
coworkModelTooSmall: "您的本地模型太小,无法用于 Cowork。请在“本地模型”中选择至少 14GB 的模型。",
|
|
116691
116898
|
moreOptions: "更多选项"
|
|
116692
116899
|
};
|
|
116693
116900
|
var chatInputFormMemoryMenu = {
|
|
@@ -116845,7 +117052,57 @@ var clawSandboxAgentSkills = {
|
|
|
116845
117052
|
fieldVersionPlaceholder: "例如:1.0.0",
|
|
116846
117053
|
fieldDescription: "描述",
|
|
116847
117054
|
fieldDescriptionPlaceholder: "例如:在网络上搜索信息",
|
|
116848
|
-
fieldInstruction: "指令"
|
|
117055
|
+
fieldInstruction: "指令",
|
|
117056
|
+
sessionNote: "在此添加或移除的技能仅对新的聊天会话生效。技能指令的修改会立即生效,包括正在进行的对话。",
|
|
117057
|
+
effectiveHeading: "此智能体的技能",
|
|
117058
|
+
catalogHeading: "可用技能",
|
|
117059
|
+
noEffectiveSkills: "此智能体尚未启用任何技能。请从下方的可用技能中添加。",
|
|
117060
|
+
addToAgent: "添加",
|
|
117061
|
+
addToAgentLabel: "将 {name} 添加到此智能体",
|
|
117062
|
+
removeFromAgent: "从智能体中移除",
|
|
117063
|
+
skillAdded: "已添加 {name}",
|
|
117064
|
+
skillRemoved: "已移除 {name}",
|
|
117065
|
+
featuredBadge: "精选",
|
|
117066
|
+
nativeBadge: "原生",
|
|
117067
|
+
privateBadge: "仅此智能体",
|
|
117068
|
+
fieldCategory: "分类",
|
|
117069
|
+
fieldCategoryPlaceholder: "例如 web、代码、数据",
|
|
117070
|
+
privateToAgent: "仅此智能体",
|
|
117071
|
+
privateToAgentHint: "私有技能仅对此智能体可用,并优先于具有相同 slug 的平台技能。",
|
|
117072
|
+
instructionHint: "使用该技能时智能体遵循的操作指南。修改会立即生效,包括正在进行的对话。",
|
|
117073
|
+
filesHint: "智能体在使用此技能时可参考的可选资源。参考资料和脚本是文本文件;资产是上传的文件。",
|
|
117074
|
+
filesAfterCreateHint: "创建技能后即可附加资源(通过“编辑”重新打开)。",
|
|
117075
|
+
noFiles: "尚未附加任何资源。",
|
|
117076
|
+
loadingFiles: "正在加载资源...",
|
|
117077
|
+
fileTypeLabel: "类型",
|
|
117078
|
+
fileTypeReference: "参考资料",
|
|
117079
|
+
fileTypeScript: "脚本",
|
|
117080
|
+
fileTypeAsset: "资源",
|
|
117081
|
+
fileNameLabel: "文件名",
|
|
117082
|
+
fileNamePlaceholder: "例如 rubric.md",
|
|
117083
|
+
fileContentLabel: "内容",
|
|
117084
|
+
fileContentPlaceholder: "文件的文本内容",
|
|
117085
|
+
addFileButton: "添加资源",
|
|
117086
|
+
adding: "添加中...",
|
|
117087
|
+
uploading: "上传中...",
|
|
117088
|
+
fileAdded: "资源已添加",
|
|
117089
|
+
fileUploaded: "资源已上传",
|
|
117090
|
+
fileSaved: "资源已保存",
|
|
117091
|
+
fileDeleted: "资源已删除",
|
|
117092
|
+
failedToSaveFile: "保存资源失败",
|
|
117093
|
+
failedToUploadFile: "上传资源失败",
|
|
117094
|
+
failedToDeleteFile: "删除资源失败",
|
|
117095
|
+
detailsTab: "常规",
|
|
117096
|
+
filesTab: "资源",
|
|
117097
|
+
newFile: "新建资源",
|
|
117098
|
+
newFileDialogTitle: "新建资源",
|
|
117099
|
+
editFileDialogTitle: "编辑资源",
|
|
117100
|
+
deleteFileDialogTitle: "删除资源",
|
|
117101
|
+
deleteFileConfirmation: "确定要删除 {name} 吗?此操作无法撤销。",
|
|
117102
|
+
chooseFile: "选择文件",
|
|
117103
|
+
upload: "上传",
|
|
117104
|
+
download: "下载",
|
|
117105
|
+
resourcesItemLabel: "资源"
|
|
116849
117106
|
};
|
|
116850
117107
|
var clawSandboxHelpers = {
|
|
116851
117108
|
unknown: "未知",
|
|
@@ -119110,7 +119367,7 @@ var safetyTabLabels = {
|
|
|
119110
119367
|
};
|
|
119111
119368
|
var screenshareTabLabels = {
|
|
119112
119369
|
header: {
|
|
119113
|
-
title: "
|
|
119370
|
+
title: "屏幕",
|
|
119114
119371
|
description: "当用户在语音通话中共享屏幕时,您的智能体的表现方式。"
|
|
119115
119372
|
},
|
|
119116
119373
|
capability: {
|
|
@@ -121045,6 +121302,19 @@ var profileApplicationsQuestionsEditor = {
|
|
|
121045
121302
|
collapseSection: "折叠板块",
|
|
121046
121303
|
expandSection: "展开板块"
|
|
121047
121304
|
};
|
|
121305
|
+
var slashSkillPicker = {
|
|
121306
|
+
listLabel: "智能体技能",
|
|
121307
|
+
resultsAnnouncement: "{count} 个技能可用。使用方向键浏览,按 Enter 选择。",
|
|
121308
|
+
loading: "加载中..."
|
|
121309
|
+
};
|
|
121310
|
+
var skillsTabLabels = {
|
|
121311
|
+
header: {
|
|
121312
|
+
title: "技能",
|
|
121313
|
+
description: "可附加到此智能体的可复用操作指南——每个技能都是完成一项任务的指令集。在聊天中输入 / 即可使用。"
|
|
121314
|
+
},
|
|
121315
|
+
notBaseAgent: "技能仅适用于基础智能体。",
|
|
121316
|
+
loading: "加载中..."
|
|
121317
|
+
};
|
|
121048
121318
|
var zh = {
|
|
121049
121319
|
accessTabAddAccess: accessTabAddAccess,
|
|
121050
121320
|
accessTabLabels: accessTabLabels,
|
|
@@ -121296,7 +121566,9 @@ var zh = {
|
|
|
121296
121566
|
placementExam: placementExam,
|
|
121297
121567
|
applyApplyWizard: applyApplyWizard,
|
|
121298
121568
|
profileApplicationsTab: profileApplicationsTab,
|
|
121299
|
-
profileApplicationsQuestionsEditor: profileApplicationsQuestionsEditor
|
|
121569
|
+
profileApplicationsQuestionsEditor: profileApplicationsQuestionsEditor,
|
|
121570
|
+
slashSkillPicker: slashSkillPicker,
|
|
121571
|
+
skillsTabLabels: skillsTabLabels
|
|
121300
121572
|
};
|
|
121301
121573
|
|
|
121302
121574
|
/**
|
|
@@ -127458,344 +127730,8 @@ var Indicator$2 = ProgressIndicator;
|
|
|
127458
127730
|
const Progress = React.forwardRef(({ className, value, ...props }, ref) => (jsx(Root$9, { ref: ref, className: cn('bg-secondary relative h-4 w-full overflow-hidden rounded-full', className), ...props, children: jsx(Indicator$2, { className: "bg-primary h-full w-full flex-1 transition-all", style: { transform: `translateX(-${100 - (value || 0)}%)` } }) })));
|
|
127459
127731
|
Progress.displayName = Root$9.displayName;
|
|
127460
127732
|
|
|
127461
|
-
var SLOTTABLE_IDENTIFIER = Symbol("radix.slottable");
|
|
127462
|
-
// @__NO_SIDE_EFFECTS__
|
|
127463
|
-
function createSlottable(ownerName) {
|
|
127464
|
-
const Slottable2 = ({ children }) => {
|
|
127465
|
-
return /* @__PURE__ */ jsx(Fragment$1, { children });
|
|
127466
|
-
};
|
|
127467
|
-
Slottable2.displayName = `${ownerName}.Slottable`;
|
|
127468
|
-
Slottable2.__radixId = SLOTTABLE_IDENTIFIER;
|
|
127469
|
-
return Slottable2;
|
|
127470
|
-
}
|
|
127471
|
-
|
|
127472
|
-
var ROOT_NAME = "AlertDialog";
|
|
127473
|
-
var [createAlertDialogContext] = createContextScope$1(ROOT_NAME, [
|
|
127474
|
-
createDialogScope
|
|
127475
|
-
]);
|
|
127476
|
-
var useDialogScope = createDialogScope();
|
|
127477
|
-
var AlertDialog$1 = (props) => {
|
|
127478
|
-
const { __scopeAlertDialog, ...alertDialogProps } = props;
|
|
127479
|
-
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
127480
|
-
return /* @__PURE__ */ jsx(DialogPrimitive.Root, { ...dialogScope, ...alertDialogProps, modal: true });
|
|
127481
|
-
};
|
|
127482
|
-
AlertDialog$1.displayName = ROOT_NAME;
|
|
127483
|
-
var TRIGGER_NAME$3 = "AlertDialogTrigger";
|
|
127484
|
-
var AlertDialogTrigger = React.forwardRef(
|
|
127485
|
-
(props, forwardedRef) => {
|
|
127486
|
-
const { __scopeAlertDialog, ...triggerProps } = props;
|
|
127487
|
-
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
127488
|
-
return /* @__PURE__ */ jsx(DialogPrimitive.Trigger, { ...dialogScope, ...triggerProps, ref: forwardedRef });
|
|
127489
|
-
}
|
|
127490
|
-
);
|
|
127491
|
-
AlertDialogTrigger.displayName = TRIGGER_NAME$3;
|
|
127492
|
-
var PORTAL_NAME$2 = "AlertDialogPortal";
|
|
127493
|
-
var AlertDialogPortal$1 = (props) => {
|
|
127494
|
-
const { __scopeAlertDialog, ...portalProps } = props;
|
|
127495
|
-
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
127496
|
-
return /* @__PURE__ */ jsx(DialogPrimitive.Portal, { ...dialogScope, ...portalProps });
|
|
127497
|
-
};
|
|
127498
|
-
AlertDialogPortal$1.displayName = PORTAL_NAME$2;
|
|
127499
|
-
var OVERLAY_NAME = "AlertDialogOverlay";
|
|
127500
|
-
var AlertDialogOverlay$1 = React.forwardRef(
|
|
127501
|
-
(props, forwardedRef) => {
|
|
127502
|
-
const { __scopeAlertDialog, ...overlayProps } = props;
|
|
127503
|
-
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
127504
|
-
return /* @__PURE__ */ jsx(DialogPrimitive.Overlay, { ...dialogScope, ...overlayProps, ref: forwardedRef });
|
|
127505
|
-
}
|
|
127506
|
-
);
|
|
127507
|
-
AlertDialogOverlay$1.displayName = OVERLAY_NAME;
|
|
127508
|
-
var CONTENT_NAME$4 = "AlertDialogContent";
|
|
127509
|
-
var [AlertDialogContentProvider, useAlertDialogContentContext] = createAlertDialogContext(CONTENT_NAME$4);
|
|
127510
|
-
var Slottable = createSlottable("AlertDialogContent");
|
|
127511
|
-
var AlertDialogContent$1 = React.forwardRef(
|
|
127512
|
-
(props, forwardedRef) => {
|
|
127513
|
-
const { __scopeAlertDialog, children, ...contentProps } = props;
|
|
127514
|
-
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
127515
|
-
const contentRef = React.useRef(null);
|
|
127516
|
-
const composedRefs = useComposedRefs$1(forwardedRef, contentRef);
|
|
127517
|
-
const cancelRef = React.useRef(null);
|
|
127518
|
-
return /* @__PURE__ */ jsx(
|
|
127519
|
-
DialogPrimitive.WarningProvider,
|
|
127520
|
-
{
|
|
127521
|
-
contentName: CONTENT_NAME$4,
|
|
127522
|
-
titleName: TITLE_NAME,
|
|
127523
|
-
docsSlug: "alert-dialog",
|
|
127524
|
-
children: /* @__PURE__ */ jsx(AlertDialogContentProvider, { scope: __scopeAlertDialog, cancelRef, children: /* @__PURE__ */ jsxs(
|
|
127525
|
-
DialogPrimitive.Content,
|
|
127526
|
-
{
|
|
127527
|
-
role: "alertdialog",
|
|
127528
|
-
...dialogScope,
|
|
127529
|
-
...contentProps,
|
|
127530
|
-
ref: composedRefs,
|
|
127531
|
-
onOpenAutoFocus: composeEventHandlers$2(contentProps.onOpenAutoFocus, (event) => {
|
|
127532
|
-
event.preventDefault();
|
|
127533
|
-
cancelRef.current?.focus({ preventScroll: true });
|
|
127534
|
-
}),
|
|
127535
|
-
onPointerDownOutside: (event) => event.preventDefault(),
|
|
127536
|
-
onInteractOutside: (event) => event.preventDefault(),
|
|
127537
|
-
children: [
|
|
127538
|
-
/* @__PURE__ */ jsx(Slottable, { children }),
|
|
127539
|
-
/* @__PURE__ */ jsx(DescriptionWarning, { contentRef })
|
|
127540
|
-
]
|
|
127541
|
-
}
|
|
127542
|
-
) })
|
|
127543
|
-
}
|
|
127544
|
-
);
|
|
127545
|
-
}
|
|
127546
|
-
);
|
|
127547
|
-
AlertDialogContent$1.displayName = CONTENT_NAME$4;
|
|
127548
|
-
var TITLE_NAME = "AlertDialogTitle";
|
|
127549
|
-
var AlertDialogTitle$1 = React.forwardRef(
|
|
127550
|
-
(props, forwardedRef) => {
|
|
127551
|
-
const { __scopeAlertDialog, ...titleProps } = props;
|
|
127552
|
-
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
127553
|
-
return /* @__PURE__ */ jsx(DialogPrimitive.Title, { ...dialogScope, ...titleProps, ref: forwardedRef });
|
|
127554
|
-
}
|
|
127555
|
-
);
|
|
127556
|
-
AlertDialogTitle$1.displayName = TITLE_NAME;
|
|
127557
|
-
var DESCRIPTION_NAME = "AlertDialogDescription";
|
|
127558
|
-
var AlertDialogDescription$1 = React.forwardRef((props, forwardedRef) => {
|
|
127559
|
-
const { __scopeAlertDialog, ...descriptionProps } = props;
|
|
127560
|
-
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
127561
|
-
return /* @__PURE__ */ jsx(DialogPrimitive.Description, { ...dialogScope, ...descriptionProps, ref: forwardedRef });
|
|
127562
|
-
});
|
|
127563
|
-
AlertDialogDescription$1.displayName = DESCRIPTION_NAME;
|
|
127564
|
-
var ACTION_NAME = "AlertDialogAction";
|
|
127565
|
-
var AlertDialogAction$1 = React.forwardRef(
|
|
127566
|
-
(props, forwardedRef) => {
|
|
127567
|
-
const { __scopeAlertDialog, ...actionProps } = props;
|
|
127568
|
-
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
127569
|
-
return /* @__PURE__ */ jsx(DialogPrimitive.Close, { ...dialogScope, ...actionProps, ref: forwardedRef });
|
|
127570
|
-
}
|
|
127571
|
-
);
|
|
127572
|
-
AlertDialogAction$1.displayName = ACTION_NAME;
|
|
127573
|
-
var CANCEL_NAME = "AlertDialogCancel";
|
|
127574
|
-
var AlertDialogCancel$1 = React.forwardRef(
|
|
127575
|
-
(props, forwardedRef) => {
|
|
127576
|
-
const { __scopeAlertDialog, ...cancelProps } = props;
|
|
127577
|
-
const { cancelRef } = useAlertDialogContentContext(CANCEL_NAME, __scopeAlertDialog);
|
|
127578
|
-
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
127579
|
-
const ref = useComposedRefs$1(forwardedRef, cancelRef);
|
|
127580
|
-
return /* @__PURE__ */ jsx(DialogPrimitive.Close, { ...dialogScope, ...cancelProps, ref });
|
|
127581
|
-
}
|
|
127582
|
-
);
|
|
127583
|
-
AlertDialogCancel$1.displayName = CANCEL_NAME;
|
|
127584
|
-
var DescriptionWarning = ({ contentRef }) => {
|
|
127585
|
-
const MESSAGE = `\`${CONTENT_NAME$4}\` requires a description for the component to be accessible for screen reader users.
|
|
127586
|
-
|
|
127587
|
-
You can add a description to the \`${CONTENT_NAME$4}\` by passing a \`${DESCRIPTION_NAME}\` component as a child, which also benefits sighted users by adding visible context to the dialog.
|
|
127588
|
-
|
|
127589
|
-
Alternatively, you can use your own component as a description by assigning it an \`id\` and passing the same value to the \`aria-describedby\` prop in \`${CONTENT_NAME$4}\`. If the description is confusing or duplicative for sighted users, you can use the \`@radix-ui/react-visually-hidden\` primitive as a wrapper around your description component.
|
|
127590
|
-
|
|
127591
|
-
For more information, see https://radix-ui.com/primitives/docs/components/alert-dialog`;
|
|
127592
|
-
React.useEffect(() => {
|
|
127593
|
-
const hasDescription = document.getElementById(
|
|
127594
|
-
contentRef.current?.getAttribute("aria-describedby")
|
|
127595
|
-
);
|
|
127596
|
-
if (!hasDescription) console.warn(MESSAGE);
|
|
127597
|
-
}, [MESSAGE, contentRef]);
|
|
127598
|
-
return null;
|
|
127599
|
-
};
|
|
127600
|
-
var Root2$4 = AlertDialog$1;
|
|
127601
|
-
var Portal2 = AlertDialogPortal$1;
|
|
127602
|
-
var Overlay2 = AlertDialogOverlay$1;
|
|
127603
|
-
var Content2$2 = AlertDialogContent$1;
|
|
127604
|
-
var Action = AlertDialogAction$1;
|
|
127605
|
-
var Cancel = AlertDialogCancel$1;
|
|
127606
|
-
var Title2 = AlertDialogTitle$1;
|
|
127607
|
-
var Description2 = AlertDialogDescription$1;
|
|
127608
|
-
|
|
127609
|
-
const AlertDialog = Root2$4;
|
|
127610
|
-
const AlertDialogPortal = Portal2;
|
|
127611
|
-
const AlertDialogOverlay = React.forwardRef(({ className, ...props }, ref) => (jsx(Overlay2, { className: cn('data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80', className), ...props, ref: ref })));
|
|
127612
|
-
AlertDialogOverlay.displayName = Overlay2.displayName;
|
|
127613
|
-
const AlertDialogContent = React.forwardRef(({ className, ...props }, ref) => (jsxs(AlertDialogPortal, { children: [jsx(AlertDialogOverlay, {}), jsx(Content2$2, { ref: ref, className: cn('bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg', className), ...props })] })));
|
|
127614
|
-
AlertDialogContent.displayName = Content2$2.displayName;
|
|
127615
|
-
const AlertDialogHeader = ({ className, ...props }) => (jsx("div", { className: cn('flex flex-col space-y-2 text-center sm:text-left', className), ...props }));
|
|
127616
|
-
AlertDialogHeader.displayName = 'AlertDialogHeader';
|
|
127617
|
-
const AlertDialogFooter = ({ className, ...props }) => (jsx("div", { className: cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className), ...props }));
|
|
127618
|
-
AlertDialogFooter.displayName = 'AlertDialogFooter';
|
|
127619
|
-
const AlertDialogTitle = React.forwardRef(({ className, ...props }, ref) => (jsx(Title2, { ref: ref, className: cn('text-lg font-semibold', className), ...props })));
|
|
127620
|
-
AlertDialogTitle.displayName = Title2.displayName;
|
|
127621
|
-
const AlertDialogDescription = React.forwardRef(({ className, ...props }, ref) => (jsx(Description2, { ref: ref, className: cn('text-muted-foreground text-sm', className), ...props })));
|
|
127622
|
-
AlertDialogDescription.displayName = Description2.displayName;
|
|
127623
|
-
const AlertDialogAction = React.forwardRef(({ className, ...props }, ref) => (jsx(Action, { ref: ref, className: cn(buttonVariants(), className), ...props })));
|
|
127624
|
-
AlertDialogAction.displayName = Action.displayName;
|
|
127625
|
-
const AlertDialogCancel = React.forwardRef(({ className, ...props }, ref) => (jsx(Cancel, { ref: ref, className: cn(buttonVariants({ variant: 'outline' }), 'mt-2 sm:mt-0', className), ...props })));
|
|
127626
|
-
AlertDialogCancel.displayName = Cancel.displayName;
|
|
127627
|
-
|
|
127628
|
-
// Tauri types for model download functionality
|
|
127629
|
-
/**
|
|
127630
|
-
* Initial state for model download
|
|
127631
|
-
*/
|
|
127632
|
-
const initialModelDownloadState = {
|
|
127633
|
-
status: 'idle',
|
|
127634
|
-
progress: 0,
|
|
127635
|
-
message: '',
|
|
127636
|
-
logs: [],
|
|
127637
|
-
lastUpdated: new Date().toISOString(),
|
|
127638
|
-
};
|
|
127639
|
-
/**
|
|
127640
|
-
* Check if the app is running inside Tauri
|
|
127641
|
-
* In Tauri 2.0, the global is __TAURI_INTERNALS__ (with withGlobalTauri: true)
|
|
127642
|
-
* We also check for __TAURI__ for backwards compatibility
|
|
127643
|
-
*/
|
|
127644
|
-
const isTauriApp$1 = () => {
|
|
127645
|
-
if (typeof window === 'undefined')
|
|
127646
|
-
return false;
|
|
127647
|
-
return '__TAURI_INTERNALS__' in window || '__TAURI__' in window;
|
|
127648
|
-
};
|
|
127649
|
-
/**
|
|
127650
|
-
* Tauri event names
|
|
127651
|
-
*/
|
|
127652
|
-
const TAURI_EVENTS = {
|
|
127653
|
-
DOWNLOAD_PROGRESS: 'model:download-progress',
|
|
127654
|
-
INSTALLATION_LOG: 'model:installation-log',
|
|
127655
|
-
DISK_SPACE_ERROR: 'model:disk-space-error',
|
|
127656
|
-
OLLAMA_STATUS: 'model:ollama-status',
|
|
127657
|
-
};
|
|
127658
|
-
/**
|
|
127659
|
-
* Tauri command names
|
|
127660
|
-
*/
|
|
127661
|
-
const TAURI_COMMANDS = {
|
|
127662
|
-
INSTALL_OLLAMA: 'install_ollama',
|
|
127663
|
-
STOP_OLLAMA: 'stop_ollama',
|
|
127664
|
-
CHECK_OLLAMA_STATUS: 'check_ollama_status',
|
|
127665
|
-
CHECK_DISK_SPACE: 'check_disk_space_for_model',
|
|
127666
|
-
GET_SYSTEM_MEMORY: 'get_system_memory',
|
|
127667
|
-
DOWNLOAD_MODEL: 'download_model',
|
|
127668
|
-
CANCEL_DOWNLOAD: 'cancel_model_download',
|
|
127669
|
-
CHECK_NETWORK_STATUS: 'check_network_status',
|
|
127670
|
-
GET_OS_TYPE: 'get_os_type',
|
|
127671
|
-
CHECK_FOUNDRY_STATUS: 'check_foundry_local_status',
|
|
127672
|
-
START_FOUNDRY_SERVICE: 'start_foundry_local_service',
|
|
127673
|
-
LOAD_FOUNDRY_MODEL: 'load_foundry_local_model',
|
|
127674
|
-
SET_SELECTED_FOUNDRY_MODEL: 'set_selected_foundry_model',
|
|
127675
|
-
GET_SELECTED_FOUNDRY_MODEL: 'get_selected_foundry_model',
|
|
127676
|
-
INSTALL_FOUNDRY: 'install_foundry',
|
|
127677
|
-
DOWNLOAD_FOUNDRY_MODEL: 'download_foundry_model_cmd',
|
|
127678
|
-
GET_RECOMMENDED_FOUNDRY_MODELS: 'get_recommended_foundry_models',
|
|
127679
|
-
LOG_STDOUT: 'log_stdout',
|
|
127680
|
-
};
|
|
127681
|
-
/**
|
|
127682
|
-
* Initial state for the System Control install flow.
|
|
127683
|
-
*/
|
|
127684
|
-
const initialGhostOsInstallState = {
|
|
127685
|
-
status: 'idle',
|
|
127686
|
-
progress: 0,
|
|
127687
|
-
message: '',
|
|
127688
|
-
logs: [],
|
|
127689
|
-
lastUpdated: new Date().toISOString(),
|
|
127690
|
-
};
|
|
127691
|
-
/**
|
|
127692
|
-
* Tauri event names emitted by the host during GhostOS install/setup.
|
|
127693
|
-
*/
|
|
127694
|
-
const GHOST_OS_TAURI_EVENTS = {
|
|
127695
|
-
INSTALL_PROGRESS: 'ghost-os:install-progress',
|
|
127696
|
-
INSTALLATION_LOG: 'ghost-os:installation-log',
|
|
127697
|
-
STATUS: 'ghost-os:status',
|
|
127698
|
-
};
|
|
127699
|
-
/**
|
|
127700
|
-
* Tauri command names the host implements for GhostOS install/setup. The web
|
|
127701
|
-
* layer invokes these; the native side performs the clone + setup.
|
|
127702
|
-
*/
|
|
127703
|
-
const GHOST_OS_TAURI_COMMANDS = {
|
|
127704
|
-
/** Install and set up GhostOS (clone repo + run setup). */
|
|
127705
|
-
INSTALL_GHOST_OS: 'install_ghost_os',
|
|
127706
|
-
/** Stop the running GhostOS manager. */
|
|
127707
|
-
STOP_GHOST_OS: 'stop_ghost_os',
|
|
127708
|
-
/** Report current {@link GhostOsStatus}. */
|
|
127709
|
-
CHECK_GHOST_OS_STATUS: 'check_ghost_os_status',
|
|
127710
|
-
};
|
|
127711
|
-
/**
|
|
127712
|
-
* Tauri command strings exposed by `tauri-plugin-macos-permissions`
|
|
127713
|
-
* (https://github.com/ayangweb/tauri-plugin-macos-permissions). GhostOS needs
|
|
127714
|
-
* macOS Accessibility permission to control the device, so the System Control
|
|
127715
|
-
* card surfaces it. These are invoked directly via `useTauri().invoke(...)` —
|
|
127716
|
-
* no extra npm dependency. The host must register the plugin in its Tauri app
|
|
127717
|
-
* (`tauri_plugin_macos_permissions::init()`). Each `CHECK_*` returns a boolean;
|
|
127718
|
-
* each `REQUEST_*` prompts / opens the relevant System Settings pane.
|
|
127719
|
-
*/
|
|
127720
|
-
const MACOS_PERMISSIONS_COMMANDS = {
|
|
127721
|
-
CHECK_ACCESSIBILITY: 'plugin:macos-permissions|check_accessibility_permission',
|
|
127722
|
-
REQUEST_ACCESSIBILITY: 'plugin:macos-permissions|request_accessibility_permission',
|
|
127723
|
-
CHECK_SCREEN_RECORDING: 'plugin:macos-permissions|check_screen_recording_permission',
|
|
127724
|
-
REQUEST_SCREEN_RECORDING: 'plugin:macos-permissions|request_screen_recording_permission',
|
|
127725
|
-
CHECK_INPUT_MONITORING: 'plugin:macos-permissions|check_input_monitoring_permission',
|
|
127726
|
-
REQUEST_INPUT_MONITORING: 'plugin:macos-permissions|request_input_monitoring_permission',
|
|
127727
|
-
CHECK_FULL_DISK_ACCESS: 'plugin:macos-permissions|check_full_disk_access_permission',
|
|
127728
|
-
REQUEST_FULL_DISK_ACCESS: 'plugin:macos-permissions|request_full_disk_access_permission',
|
|
127729
|
-
};
|
|
127730
|
-
|
|
127731
|
-
/**
|
|
127732
|
-
* Dynamically import Tauri APIs to avoid SSR issues
|
|
127733
|
-
*/
|
|
127734
|
-
const getTauriAPIs = async () => {
|
|
127735
|
-
try {
|
|
127736
|
-
const { invoke } = await import('@tauri-apps/api/core');
|
|
127737
|
-
const { listen } = await import('@tauri-apps/api/event');
|
|
127738
|
-
return { invoke, listen };
|
|
127739
|
-
}
|
|
127740
|
-
catch (error) {
|
|
127741
|
-
console.error('Failed to load Tauri APIs:', error);
|
|
127742
|
-
return null;
|
|
127743
|
-
}
|
|
127744
|
-
};
|
|
127745
|
-
/**
|
|
127746
|
-
* Hook to access Tauri APIs with SSR safety
|
|
127747
|
-
*
|
|
127748
|
-
* @returns Object with isAvailable flag and Tauri invoke/listen functions
|
|
127749
|
-
*/
|
|
127750
|
-
function useTauri() {
|
|
127751
|
-
const [isAvailable, setIsAvailable] = useState(false);
|
|
127752
|
-
const [apis, setApis] = useState(null);
|
|
127753
|
-
useEffect(() => {
|
|
127754
|
-
// Check if we're in a Tauri environment
|
|
127755
|
-
const inTauri = isTauriApp$1();
|
|
127756
|
-
if (inTauri) {
|
|
127757
|
-
getTauriAPIs().then((result) => {
|
|
127758
|
-
setApis(result);
|
|
127759
|
-
setIsAvailable(!!result);
|
|
127760
|
-
});
|
|
127761
|
-
}
|
|
127762
|
-
}, []);
|
|
127763
|
-
/**
|
|
127764
|
-
* Invoke a Tauri command
|
|
127765
|
-
*/
|
|
127766
|
-
const invoke = useCallback(async (command, args) => {
|
|
127767
|
-
if (!(apis === null || apis === void 0 ? void 0 : apis.invoke)) {
|
|
127768
|
-
throw new Error('Tauri is not available');
|
|
127769
|
-
}
|
|
127770
|
-
return apis.invoke(command, args);
|
|
127771
|
-
}, [apis]);
|
|
127772
|
-
/**
|
|
127773
|
-
* Listen to a Tauri event
|
|
127774
|
-
* Returns an unlisten function that should be called on cleanup
|
|
127775
|
-
*/
|
|
127776
|
-
const listen = useCallback(async (event, handler) => {
|
|
127777
|
-
// The synchronous global (`__TAURI_INTERNALS__`) exposes `invoke` but
|
|
127778
|
-
// frequently NOT `event.listen`, so `apis.listen` can be undefined even
|
|
127779
|
-
// though Tauri is fully available. Fall back to the real event API via
|
|
127780
|
-
// dynamic import so download progress/completion events are actually
|
|
127781
|
-
// delivered — otherwise the UI never leaves the "downloading" state.
|
|
127782
|
-
let listenFn = apis === null || apis === void 0 ? void 0 : apis.listen;
|
|
127783
|
-
if (!listenFn) {
|
|
127784
|
-
const { listen: importedListen } = await import('@tauri-apps/api/event');
|
|
127785
|
-
listenFn = importedListen;
|
|
127786
|
-
}
|
|
127787
|
-
return listenFn(event, (e) => handler(e.payload));
|
|
127788
|
-
}, [apis]);
|
|
127789
|
-
return {
|
|
127790
|
-
isAvailable,
|
|
127791
|
-
invoke,
|
|
127792
|
-
listen,
|
|
127793
|
-
};
|
|
127794
|
-
}
|
|
127795
|
-
|
|
127796
127733
|
const LOCAL_LLM_ENABLED_KEY = 'ibl_local_llm_enabled';
|
|
127797
127734
|
const LOCAL_LLM_MODEL_KEY = 'ibl_local_llm_model';
|
|
127798
|
-
const LOCAL_LLM_TOOL_SUPPORT_KEY = 'ibl_local_llm_tool_support';
|
|
127799
127735
|
/**
|
|
127800
127736
|
* Curated catalog of small, on-device-friendly models from the Ollama library
|
|
127801
127737
|
* (https://ollama.com/library). The model manager itself (Ollama) is not a
|
|
@@ -127828,8 +127764,8 @@ const LOCAL_MODELS = [
|
|
|
127828
127764
|
},
|
|
127829
127765
|
{ name: 'Granite 4.1', provider: 'IBM', id: 'granite4.1:8b', size: '5.3 GB', tool_support: true },
|
|
127830
127766
|
{ name: 'GPT-OSS 20B', provider: 'OpenAI', id: 'gpt-oss:20b', size: '14 GB', tool_support: true },
|
|
127831
|
-
// Larger models. Sizes use "GB" so they parse for the
|
|
127832
|
-
// (only models above the configured gate can use
|
|
127767
|
+
// Larger models. Sizes use "GB" so they parse for the Cowork size gate
|
|
127768
|
+
// (only models above the configured gate can use Cowork).
|
|
127833
127769
|
{
|
|
127834
127770
|
name: 'Qwen 3.6',
|
|
127835
127771
|
provider: 'Alibaba',
|
|
@@ -127853,34 +127789,6 @@ const LOCAL_MODELS = [
|
|
|
127853
127789
|
tool_support: true,
|
|
127854
127790
|
},
|
|
127855
127791
|
];
|
|
127856
|
-
/** The model wired to the existing single-model download flow (default selection). */
|
|
127857
|
-
const PRIMARY_MODEL_ID = 'phi4-mini:latest';
|
|
127858
|
-
/**
|
|
127859
|
-
* Whether a catalog model id (e.g. "llama3.2", "phi3:mini") is present among the
|
|
127860
|
-
* installed Ollama tags reported by the backend (e.g. "llama3.2:latest"). Matches
|
|
127861
|
-
* an exact tag or the same base model with any tag suffix, so a model pulled as
|
|
127862
|
-
* `<id>:latest` still counts as installed.
|
|
127863
|
-
*/
|
|
127864
|
-
function isModelInstalled(modelId, installedTags) {
|
|
127865
|
-
if (!installedTags)
|
|
127866
|
-
return false;
|
|
127867
|
-
return installedTags.some((tag) => tag === modelId || tag.startsWith(`${modelId}:`));
|
|
127868
|
-
}
|
|
127869
|
-
/**
|
|
127870
|
-
* Whether a model id is an Ollama cloud-hosted model — either the plain ":cloud"
|
|
127871
|
-
* tag (e.g. "glm-5.2:cloud") or a sized cloud tag (e.g. "gemma4:31b-cloud").
|
|
127872
|
-
* Cloud models run on Ollama's servers, so they are available by default — never
|
|
127873
|
-
* downloaded, no local memory required, always "ready".
|
|
127874
|
-
*/
|
|
127875
|
-
function isCloudModelId(modelId) {
|
|
127876
|
-
return modelId.endsWith(':cloud') || (modelId.includes(':') && modelId.endsWith('-cloud'));
|
|
127877
|
-
}
|
|
127878
|
-
/**
|
|
127879
|
-
* Fraction of the machine's memory above which a model is treated as "too large"
|
|
127880
|
-
* and a confirmation is required before downloading. TESTING VALUE — set low (1%)
|
|
127881
|
-
* so the warning is easy to trigger; raise toward real capacity (e.g. 0.8) later.
|
|
127882
|
-
*/
|
|
127883
|
-
const MODEL_SIZE_WARN_FRACTION = 0.01;
|
|
127884
127792
|
/** Multipliers for the size units used in the catalog (binary / 1024-based). */
|
|
127885
127793
|
const SIZE_UNIT_BYTES = {
|
|
127886
127794
|
B: 1,
|
|
@@ -127902,54 +127810,19 @@ function parseModelSizeBytes(size) {
|
|
|
127902
127810
|
return null;
|
|
127903
127811
|
return value * ((_a = SIZE_UNIT_BYTES[match[2].toUpperCase()]) !== null && _a !== void 0 ? _a : 1);
|
|
127904
127812
|
}
|
|
127905
|
-
/** Format a byte count as a short, human-readable size (e.g. "16.0 GB"). */
|
|
127906
|
-
function formatBytes(bytes) {
|
|
127907
|
-
if (bytes <= 0)
|
|
127908
|
-
return '0 GB';
|
|
127909
|
-
const gb = bytes / 1024 ** 3;
|
|
127910
|
-
if (gb >= 1)
|
|
127911
|
-
return `${gb.toFixed(1)} GB`;
|
|
127912
|
-
return `${Math.round(bytes / 1024 ** 2)} MB`;
|
|
127913
|
-
}
|
|
127914
127813
|
/**
|
|
127915
|
-
*
|
|
127916
|
-
* VRAM (a model runs in one or the other). Returns 0 when memory is unknown.
|
|
127917
|
-
*/
|
|
127918
|
-
function usableMemoryBytes(systemMemory) {
|
|
127919
|
-
if (!systemMemory)
|
|
127920
|
-
return 0;
|
|
127921
|
-
return Math.max(systemMemory.ram_total, systemMemory.vram_total);
|
|
127922
|
-
}
|
|
127923
|
-
/**
|
|
127924
|
-
* Whether `model` is large enough relative to this machine's memory to warrant a
|
|
127925
|
-
* "might not run" confirmation. False when memory or the model size is unknown,
|
|
127926
|
-
* so the download simply proceeds rather than warning on incomplete data.
|
|
127927
|
-
*/
|
|
127928
|
-
function modelExceedsCapacity(model, systemMemory) {
|
|
127929
|
-
const capacity = usableMemoryBytes(systemMemory);
|
|
127930
|
-
const modelBytes = parseModelSizeBytes(model.size);
|
|
127931
|
-
if (modelBytes == null)
|
|
127932
|
-
return false;
|
|
127933
|
-
// Unknown memory (capacity 0) → don't warn; the download simply proceeds
|
|
127934
|
-
// rather than blocking on incomplete data.
|
|
127935
|
-
if (capacity <= 0)
|
|
127936
|
-
return false;
|
|
127937
|
-
return modelBytes > capacity * MODEL_SIZE_WARN_FRACTION;
|
|
127938
|
-
}
|
|
127939
|
-
/**
|
|
127940
|
-
* Default minimum model size (GB) that can use the System Control Manager
|
|
127814
|
+
* Default minimum model size (GB) that can use the Cowork
|
|
127941
127815
|
* (GhostOS MCP/tools). Smaller models don't support tools/MCP well, so the
|
|
127942
|
-
* manager is gated to models above this size.
|
|
127943
|
-
* System Control card's `requiredSizeGb` prop (see SystemControlTabProps).
|
|
127816
|
+
* manager is gated to models above this size.
|
|
127944
127817
|
*/
|
|
127945
|
-
const
|
|
127818
|
+
const DEFAULT_COWORK_REQUIRED_SIZE_GB = 12;
|
|
127946
127819
|
/**
|
|
127947
127820
|
* Whether the given model (by Ollama id) is large enough to use the System
|
|
127948
127821
|
* Control Manager — i.e. its catalog size exceeds `gb` (default
|
|
127949
|
-
* {@link
|
|
127822
|
+
* {@link DEFAULT_COWORK_REQUIRED_SIZE_GB}). Unknown ids or unparseable
|
|
127950
127823
|
* sizes return false (gated off).
|
|
127951
127824
|
*/
|
|
127952
|
-
function
|
|
127825
|
+
function modelSupportsCowork(modelId, gb = DEFAULT_COWORK_REQUIRED_SIZE_GB) {
|
|
127953
127826
|
if (!modelId)
|
|
127954
127827
|
return false;
|
|
127955
127828
|
const model = LOCAL_MODELS.find((m) => m.id === modelId);
|
|
@@ -127960,22 +127833,6 @@ function modelSupportsSystemControl(modelId, gb = DEFAULT_SYSTEM_CONTROL_REQUIRE
|
|
|
127960
127833
|
return false;
|
|
127961
127834
|
return bytes > gb * 1024 ** 3;
|
|
127962
127835
|
}
|
|
127963
|
-
/**
|
|
127964
|
-
* The smallest catalog model that can use the System Control Manager (size
|
|
127965
|
-
* exceeds `gb`), or null if none qualify. Used by the "Upgrade" action to pick
|
|
127966
|
-
* the lightest capable model. Ties / unparseable sizes sort last.
|
|
127967
|
-
*/
|
|
127968
|
-
function smallestSystemControlModel(gb = DEFAULT_SYSTEM_CONTROL_REQUIRED_SIZE_GB) {
|
|
127969
|
-
const usable = LOCAL_MODELS.filter((m) => modelSupportsSystemControl(m.id, gb));
|
|
127970
|
-
if (usable.length === 0)
|
|
127971
|
-
return null;
|
|
127972
|
-
return usable.reduce((smallest, m) => {
|
|
127973
|
-
var _a, _b;
|
|
127974
|
-
const a = (_a = parseModelSizeBytes(m.size)) !== null && _a !== void 0 ? _a : Infinity;
|
|
127975
|
-
const b = (_b = parseModelSizeBytes(smallest.size)) !== null && _b !== void 0 ? _b : Infinity;
|
|
127976
|
-
return a < b ? m : smallest;
|
|
127977
|
-
});
|
|
127978
|
-
}
|
|
127979
127836
|
/**
|
|
127980
127837
|
* Check if local LLM is enabled from localStorage
|
|
127981
127838
|
*/
|
|
@@ -128000,57 +127857,21 @@ function getLocalLLMModel() {
|
|
|
128000
127857
|
return null;
|
|
128001
127858
|
return localStorage.getItem(LOCAL_LLM_MODEL_KEY);
|
|
128002
127859
|
}
|
|
128003
|
-
|
|
128004
|
-
|
|
128005
|
-
*/
|
|
128006
|
-
function setLocalLLMModel(modelId) {
|
|
128007
|
-
if (typeof window === 'undefined')
|
|
128008
|
-
return;
|
|
128009
|
-
localStorage.setItem(LOCAL_LLM_MODEL_KEY, modelId);
|
|
128010
|
-
}
|
|
128011
|
-
/**
|
|
128012
|
-
* Persist whether the selected model supports tools (set when a model is chosen).
|
|
128013
|
-
*/
|
|
128014
|
-
function setLocalLLMToolSupport(toolSupport) {
|
|
128015
|
-
if (typeof window === 'undefined')
|
|
128016
|
-
return;
|
|
128017
|
-
localStorage.setItem(LOCAL_LLM_TOOL_SUPPORT_KEY, String(toolSupport));
|
|
128018
|
-
}
|
|
128019
|
-
function LocalLLMTab({ isAvailable, state, ollamaStatus, systemMemory, isUsingFoundry = false, foundryModels = [], selectedFoundryModel = null, foundryStatus, onStartDownload, onCancelDownload, onInstallOllama, onStopManager, onInstallFoundry, onCheckStatus, onResetState, onSelectFoundryModel, }) {
|
|
128020
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
127860
|
+
function LocalLLMTab({ isAvailable, state, ollamaStatus, isUsingFoundry = false, foundryModels = [], selectedFoundryModel = null, foundryStatus, onInstallOllama, onStopManager, onInstallFoundry, onCheckStatus, onSelectFoundryModel, }) {
|
|
127861
|
+
var _a, _b, _c, _d, _e;
|
|
128021
127862
|
const t = useT();
|
|
128022
|
-
// Direct Tauri access so the model-size check can read system memory fresh at
|
|
128023
|
-
// download-click time (the threaded `systemMemory` prop is only a fast path).
|
|
128024
|
-
const { invoke } = useTauri();
|
|
128025
127863
|
const isDownloading = state.status === 'downloading';
|
|
128026
127864
|
const isManagerInstalling = state.managerInstalling || (ollamaStatus === null || ollamaStatus === void 0 ? void 0 : ollamaStatus.installing);
|
|
128027
127865
|
// User preference state - independent of whether model is installed
|
|
128028
127866
|
const [isEnabled, setIsEnabled] = useState(() => isLocalLLMEnabled());
|
|
128029
|
-
// Which model the shared download flow currently targets. Prefer the model
|
|
128030
|
-
// recorded in the persisted download state, so the correct row shows progress
|
|
128031
|
-
// even after the dialog is closed and reopened mid-download; fall back to a
|
|
128032
|
-
// local value for immediate feedback the instant a Download button is clicked.
|
|
128033
|
-
const [localActiveModelId, setLocalActiveModelId] = useState(PRIMARY_MODEL_ID);
|
|
128034
|
-
const activeModelId = state.status === 'downloading' && state.activeModel ? state.activeModel : localActiveModelId;
|
|
128035
|
-
// Which model the user has chosen to chat with (exclusive selection).
|
|
128036
|
-
const [selectedModelId, setSelectedModelId] = useState(() => getLocalLLMModel() || PRIMARY_MODEL_ID);
|
|
128037
|
-
// A model the user asked to download that is large relative to this machine's
|
|
128038
|
-
// memory. Set when we need the user to confirm a "might not run" warning before
|
|
128039
|
-
// starting the download; null when no confirmation is pending.
|
|
128040
|
-
const [pendingModel, setPendingModel] = useState(null);
|
|
128041
127867
|
// "Enable Local Models" === run the model manager (Ollama). The toggle is a
|
|
128042
127868
|
// user preference that is always operable: turning it on installs (if needed)
|
|
128043
|
-
// and starts the manager; turning it off stops it.
|
|
128044
|
-
// shown whenever the toggle is on
|
|
128045
|
-
//
|
|
127869
|
+
// and starts the manager; turning it off stops it. Only the manager status
|
|
127870
|
+
// card is shown here (whenever the toggle is on or mid-install) — the per-model
|
|
127871
|
+
// list lives in Agent settings → LLM tab, where local models are picked and
|
|
127872
|
+
// downloaded alongside cloud models.
|
|
128046
127873
|
const managerRunning = (ollamaStatus === null || ollamaStatus === void 0 ? void 0 : ollamaStatus.running) === true;
|
|
128047
127874
|
const localModelsEnabled = isEnabled || isManagerInstalling;
|
|
128048
|
-
// A model can be chosen for chat only once it is downloaded/ready. The backend
|
|
128049
|
-
// reports every installed model tag, so any downloaded model qualifies.
|
|
128050
|
-
const selectedModelReady = isCloudModelId(selectedModelId) ||
|
|
128051
|
-
isModelInstalled(selectedModelId, ollamaStatus === null || ollamaStatus === void 0 ? void 0 : ollamaStatus.installed_models) ||
|
|
128052
|
-
(selectedModelId === PRIMARY_MODEL_ID &&
|
|
128053
|
-
(state.status === 'completed' || (ollamaStatus === null || ollamaStatus === void 0 ? void 0 : ollamaStatus.model_installed) === true));
|
|
128054
127875
|
// Track previous model installation state to detect when it first becomes installed
|
|
128055
127876
|
const [, setWasModelInstalled] = useState(() => {
|
|
128056
127877
|
return (ollamaStatus === null || ollamaStatus === void 0 ? void 0 : ollamaStatus.model_installed) === true;
|
|
@@ -128164,62 +127985,6 @@ function LocalLLMTab({ isAvailable, state, ollamaStatus, systemMemory, isUsingFo
|
|
|
128164
127985
|
onStopManager === null || onStopManager === void 0 ? void 0 : onStopManager();
|
|
128165
127986
|
}
|
|
128166
127987
|
};
|
|
128167
|
-
const startDownloadNow = (modelId) => {
|
|
128168
|
-
setLocalActiveModelId(modelId);
|
|
128169
|
-
onStartDownload(modelId);
|
|
128170
|
-
};
|
|
128171
|
-
const handleDownloadModel = async (modelId) => {
|
|
128172
|
-
// Always read system memory FIRST — this is the call that hits the backend
|
|
128173
|
-
// `get_system_memory`. Doing it before the catalog lookup guarantees it runs
|
|
128174
|
-
// on every Download click (falling back to the value fetched on mount).
|
|
128175
|
-
const model = LOCAL_MODELS.find((m) => modelId.startsWith(m.id));
|
|
128176
|
-
if (!model) {
|
|
128177
|
-
await invoke(TAURI_COMMANDS.LOG_STDOUT, {
|
|
128178
|
-
s: `[Local Models] -> Download: bad download request, model ${model}`,
|
|
128179
|
-
});
|
|
128180
|
-
console.log(`[Local Models] -> Download: bad download request, model ${model}`);
|
|
128181
|
-
return;
|
|
128182
|
-
}
|
|
128183
|
-
let mem = null;
|
|
128184
|
-
try {
|
|
128185
|
-
mem = await invoke(TAURI_COMMANDS.GET_SYSTEM_MEMORY);
|
|
128186
|
-
}
|
|
128187
|
-
catch (e) {
|
|
128188
|
-
await invoke(TAURI_COMMANDS.LOG_STDOUT, {
|
|
128189
|
-
s: `[Local Models] -> Download: couldn't detect system memory ${modelId} ${e}`,
|
|
128190
|
-
});
|
|
128191
|
-
console.log(`[Local Models] -> Download: couldn't detect system memory {e}`);
|
|
128192
|
-
return;
|
|
128193
|
-
}
|
|
128194
|
-
const exceeds = modelExceedsCapacity(model, mem);
|
|
128195
|
-
console.warn('[Local Models] -> Download: download click', {
|
|
128196
|
-
modelId,
|
|
128197
|
-
systemMemory: mem,
|
|
128198
|
-
capacityBytes: usableMemoryBytes(mem),
|
|
128199
|
-
modelBytes: parseModelSizeBytes(model.size),
|
|
128200
|
-
thresholdBytes: usableMemoryBytes(mem) * MODEL_SIZE_WARN_FRACTION,
|
|
128201
|
-
exceeds,
|
|
128202
|
-
});
|
|
128203
|
-
if (exceeds) {
|
|
128204
|
-
setPendingModel(model);
|
|
128205
|
-
return;
|
|
128206
|
-
}
|
|
128207
|
-
startDownloadNow(modelId);
|
|
128208
|
-
};
|
|
128209
|
-
const confirmPendingDownload = () => {
|
|
128210
|
-
if (pendingModel) {
|
|
128211
|
-
startDownloadNow(pendingModel.id);
|
|
128212
|
-
}
|
|
128213
|
-
setPendingModel(null);
|
|
128214
|
-
};
|
|
128215
|
-
const handleSelectModel = (modelId) => {
|
|
128216
|
-
var _a, _b;
|
|
128217
|
-
setSelectedModelId(modelId);
|
|
128218
|
-
setLocalLLMModel(modelId);
|
|
128219
|
-
// Persist the model's tool-calling support so the host can route chat to the
|
|
128220
|
-
// MCP/tool proxy (:8000) vs plain Ollama (:11434).
|
|
128221
|
-
setLocalLLMToolSupport((_b = (_a = LOCAL_MODELS.find((m) => m.id === modelId)) === null || _a === void 0 ? void 0 : _a.tool_support) !== null && _b !== void 0 ? _b : false);
|
|
128222
|
-
};
|
|
128223
127988
|
// For Ollama the switch reflects the user's toggle preference (always
|
|
128224
127989
|
// operable, so it can be turned off). Foundry additionally requires a
|
|
128225
127990
|
// downloaded model to be considered "on".
|
|
@@ -128233,54 +127998,16 @@ function LocalLLMTab({ isAvailable, state, ollamaStatus, systemMemory, isUsingFo
|
|
|
128233
127998
|
const switchDisabled = isUsingFoundry
|
|
128234
127999
|
? !hasDownloadedFoundryModel || isDownloading || state.status === 'checking'
|
|
128235
128000
|
: isDownloading || isManagerInstalling || state.status === 'checking';
|
|
128236
|
-
return (
|
|
128237
|
-
|
|
128238
|
-
|
|
128239
|
-
|
|
128240
|
-
|
|
128241
|
-
|
|
128242
|
-
|
|
128243
|
-
|
|
128244
|
-
|
|
128245
|
-
|
|
128246
|
-
// A model is ready once Ollama reports its tag as installed.
|
|
128247
|
-
// Fall back to (a) this row's own download having just
|
|
128248
|
-
// completed — so it flips to "Ready" before the status
|
|
128249
|
-
// refresh lands — and (b) the primary-model status flag.
|
|
128250
|
-
// Cloud models are ready by default.
|
|
128251
|
-
const isInstalled = isCloud ||
|
|
128252
|
-
isModelInstalled(model.id, ollamaStatus === null || ollamaStatus === void 0 ? void 0 : ollamaStatus.installed_models) ||
|
|
128253
|
-
(isActive && state.status === 'completed') ||
|
|
128254
|
-
(isPrimary && (ollamaStatus === null || ollamaStatus === void 0 ? void 0 : ollamaStatus.model_installed) === true);
|
|
128255
|
-
// An installed model must never render a download/cancel
|
|
128256
|
-
// state — guards against a stale persisted "downloading"
|
|
128257
|
-
// status making an already-ready model look like it's
|
|
128258
|
-
// still downloading (and wrongly cancellable) on reopen.
|
|
128259
|
-
const rowDownloading = isActive && isDownloading && !isInstalled;
|
|
128260
|
-
const rowChecking = isActive && state.status === 'checking';
|
|
128261
|
-
const rowError = isActive && state.status === 'error';
|
|
128262
|
-
const rowCancelled = isActive && state.status === 'cancelled';
|
|
128263
|
-
const canDownload = !!(ollamaStatus === null || ollamaStatus === void 0 ? void 0 : ollamaStatus.installed) &&
|
|
128264
|
-
!isInstalled &&
|
|
128265
|
-
!rowDownloading &&
|
|
128266
|
-
!rowChecking;
|
|
128267
|
-
const isSelected = selectedModelId === model.id;
|
|
128268
|
-
return (jsxs("tr", { className: isSelected ? 'bg-blue-50/40 dark:bg-blue-950/20' : undefined, children: [jsx("td", { className: "px-6 py-4", children: jsx("input", { type: "radio", name: "local-llm-model", checked: isSelected, disabled: !isInstalled, onChange: () => handleSelectModel(model.id), "aria-label": t('localLlmLocalLlmTab.useModelForChatAriaLabel', {
|
|
128269
|
-
name: model.name,
|
|
128270
|
-
}), title: isInstalled
|
|
128271
|
-
? undefined
|
|
128272
|
-
: t('localLlmLocalLlmTab.downloadToChatTitle'), className: isInstalled
|
|
128273
|
-
? 'h-4 w-4 cursor-pointer accent-blue-500'
|
|
128274
|
-
: 'h-4 w-4 cursor-not-allowed opacity-40' }) }), jsxs("td", { className: "px-6 py-4 whitespace-nowrap", children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx("span", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: model.name }), jsx("span", { className: "text-xs text-gray-400 dark:text-gray-500", children: model.size })] }), jsx("div", { className: "text-xs text-gray-500 dark:text-gray-400", children: model.provider })] }), jsx("td", { className: "px-6 py-4", children: jsx("div", { className: "space-y-2", children: isCloud ? (jsxs("span", { className: "inline-flex items-center gap-1 px-2 py-0.5 text-xs font-medium bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300 rounded-full", children: [jsx(Cloud, { className: "h-3 w-3" }), t('localLlmLocalLlmTab.cloud')] })) : rowDownloading ? (jsxs("div", { className: "space-y-2", children: [jsxs("span", { className: "inline-flex items-center gap-1 px-2 py-0.5 text-xs font-medium bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300 rounded-full", children: [jsx(LoaderCircle, { className: "h-3 w-3 animate-spin" }), Math.round(state.progress), "%"] }), jsx("div", { className: "w-full max-w-[200px]", children: jsx(Progress, { value: state.progress, className: "h-1.5" }) })] })) : rowChecking ? (jsxs("span", { className: "inline-flex items-center gap-1 px-2 py-0.5 text-xs font-medium bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-300 rounded-full", children: [jsx(LoaderCircle, { className: "h-3 w-3 animate-spin" }), t('localLlmLocalLlmTab.checking')] })) : isInstalled ? (jsxs("span", { className: "inline-flex items-center gap-1 px-2 py-0.5 text-xs font-medium bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300 rounded-full", children: [jsx(CircleCheckBig, { className: "h-3 w-3" }), t('localLlmLocalLlmTab.ready')] })) : rowError ? (jsxs("div", { className: "space-y-1", children: [jsxs("span", { className: "inline-flex items-center gap-1 px-2 py-0.5 text-xs font-medium bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-300 rounded-full", children: [jsx(CircleX, { className: "h-3 w-3" }), t('localLlmLocalLlmTab.error')] }), state.error && (jsx("p", { className: "text-xs text-red-600 dark:text-red-400 max-w-[200px]", children: state.error }))] })) : rowCancelled ? (jsxs("span", { className: "inline-flex items-center gap-1 px-2 py-0.5 text-xs font-medium bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-300 rounded-full", children: [jsx(X$2, { className: "h-3 w-3" }), t('localLlmLocalLlmTab.cancelled')] })) : (jsx("span", { className: "inline-flex items-center gap-1 px-2 py-0.5 text-xs font-medium bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-300 rounded-full", children: t('localLlmLocalLlmTab.notDownloaded') })) }) }), jsx("td", { className: "px-6 py-4 text-right", children: jsxs("div", { className: "flex items-center justify-end gap-2", children: [rowDownloading && (jsxs(Button$1, { onClick: onCancelDownload, variant: "outline", size: "sm", children: [jsx(X$2, { className: "h-4 w-4 mr-2" }), t('localLlmLocalLlmTab.cancel')] })), canDownload && (jsxs(Button$1, { onClick: () => handleDownloadModel(model.id), size: "sm", variant: "outline", children: [jsx(Download, { className: "h-4 w-4 mr-2" }), t('localLlmLocalLlmTab.download')] })), rowError && (jsx(Button$1, { onClick: onResetState, variant: "ghost", size: "sm", children: t('localLlmLocalLlmTab.reset') })), isInstalled && !isCloud && (jsx(Button$1, { onClick: onCheckStatus, variant: "ghost", size: "sm", children: jsx(RefreshCw, { className: "h-4 w-4" }) }))] }) })] }, model.id));
|
|
128275
|
-
}) })] }), jsx("div", { className: "px-6 py-3 border-t text-xs text-gray-500 dark:text-gray-400", style: { borderColor: 'oklch(.922 0 0)' }, children: selectedModelReady ? (jsxs(Fragment$1, { children: [t('localLlmLocalLlmTab.chattingWith'), ' ', jsx("span", { className: "font-medium text-gray-900 dark:text-gray-100", children: (_c = (_b = LOCAL_MODELS.find((m) => m.id === selectedModelId)) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : selectedModelId })] })) : (jsx(Fragment$1, { children: t('localLlmLocalLlmTab.noModelSelectedHint') })) })] }))] })) : (jsx("div", { className: "rounded-lg border px-6 py-4 bg-green-50/30 dark:bg-green-950/10", style: { borderColor: 'oklch(.922 0 0)' }, children: jsxs("div", { className: "space-y-4", children: [jsx("div", { className: "flex items-center justify-between", children: jsxs("div", { className: "flex items-center gap-3", children: [jsx(CircleCheckBig, { className: "h-8 w-8 text-green-500 flex-shrink-0" }), jsxs("div", { className: "flex-1", children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx("h3", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: t('localLlmLocalLlmTab.offlineAiReady') }), jsxs("span", { className: "inline-flex items-center gap-1 px-2 py-0.5 text-xs font-semibold bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-300 rounded-full", children: [jsx(Star$1, { className: "h-3 w-3 fill-blue-700 dark:fill-blue-300" }), t('localLlmLocalLlmTab.preferredBadge')] })] }), jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: t('localLlmLocalLlmTab.foundryReadyDescription') })] })] }) }), foundryModels.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx("label", { className: "text-xs font-medium text-gray-700 dark:text-gray-300", children: t('localLlmLocalLlmTab.selectModelLabel') }), jsxs(Select$1, { value: selectedFoundryModel || ((_d = foundryModels[0]) === null || _d === void 0 ? void 0 : _d.id), onValueChange: (value) => onSelectFoundryModel === null || onSelectFoundryModel === void 0 ? void 0 : onSelectFoundryModel(value), children: [jsx(SelectTrigger, { className: "w-full bg-gray-50 border-gray-200 dark:bg-gray-800 dark:border-gray-700", children: jsx(SelectValue, { placeholder: t('localLlmLocalLlmTab.selectModelPlaceholder') }) }), jsx(SelectContent, { children: foundryModels.map((model) => (jsx(SelectItem, { value: model.id, children: jsxs("div", { className: "flex items-center justify-between w-full gap-4", children: [jsx("span", { className: "font-medium", children: model.name || model.id }), jsxs("div", { className: "flex items-center gap-2 text-xs text-gray-500", children: [model.device && (jsx("span", { className: "px-2 py-0.5 bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300 rounded", children: model.device })), model.size && jsx("span", { children: model.size }), !model.is_downloaded && (jsx("span", { className: "px-2 py-0.5 bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-300 rounded", children: t('localLlmLocalLlmTab.notDownloaded') })), model.is_downloaded && (jsx("span", { className: "px-2 py-0.5 bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300 rounded", children: t('localLlmLocalLlmTab.downloaded') }))] })] }) }, model.id))) })] }), jsxs("div", { className: "flex flex-col gap-1", children: [jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: t('localLlmLocalLlmTab.modelsAvailable', { count: foundryModels.length }) }), selectedFoundryModel && (jsxs("div", { className: "flex items-center gap-1.5 text-xs text-green-600 dark:text-green-400", children: [jsx(CircleCheckBig, { className: "h-3.5 w-3.5" }), jsxs("span", { children: [t('localLlmLocalLlmTab.usingModelPrefix'), ' ', ((_e = foundryModels.find((m) => m.id === selectedFoundryModel)) === null || _e === void 0 ? void 0 : _e.name) ||
|
|
128276
|
-
selectedFoundryModel, ((_f = foundryModels.find((m) => m.id === selectedFoundryModel)) === null || _f === void 0 ? void 0 : _f.device) && (jsxs("span", { className: "ml-1 text-gray-500 dark:text-gray-400", children: ["(", (_g = foundryModels.find((m) => m.id === selectedFoundryModel)) === null || _g === void 0 ? void 0 : _g.device, ")"] }))] })] }))] })] })), state.status === 'downloading' && (jsxs("div", { className: "mt-4 p-4 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg", children: [jsxs("div", { className: "flex items-center gap-3", children: [jsx("div", { className: "animate-spin h-5 w-5 border-2 border-blue-600 dark:border-blue-400 border-t-transparent rounded-full" }), jsxs("div", { className: "flex-1", children: [jsx("p", { className: "text-sm font-medium text-blue-900 dark:text-blue-100", children: state.message }), state.progress > 0 && (jsx("div", { className: "mt-2 w-full bg-blue-200 dark:bg-blue-800 rounded-full h-2", children: jsx("div", { className: "bg-blue-600 dark:bg-blue-400 h-2 rounded-full transition-all duration-300", style: { width: `${state.progress}%` } }) }))] })] }), state.logs.length > 0 && (jsx("div", { className: "mt-3 max-h-32 overflow-y-auto bg-white dark:bg-gray-800 rounded border border-blue-200 dark:border-blue-700 p-2", children: state.logs.slice(-10).map((log, idx) => (jsx("div", { className: `text-xs font-mono ${log.level === 'error'
|
|
128277
|
-
? 'text-red-600 dark:text-red-400'
|
|
128278
|
-
: log.level === 'warn'
|
|
128279
|
-
? 'text-yellow-600 dark:text-yellow-400'
|
|
128280
|
-
: 'text-gray-700 dark:text-gray-300'}`, children: log.message }, idx))) }))] }))] }) }))] }), jsx(AlertDialog, { open: !!pendingModel, onOpenChange: (open) => {
|
|
128281
|
-
if (!open)
|
|
128282
|
-
setPendingModel(null);
|
|
128283
|
-
}, children: jsxs(AlertDialogContent, { children: [jsxs(AlertDialogHeader, { children: [jsx(AlertDialogTitle, { children: "This model may be too large for your system" }), jsxs(AlertDialogDescription, { children: [pendingModel === null || pendingModel === void 0 ? void 0 : pendingModel.name, " needs about ", pendingModel === null || pendingModel === void 0 ? void 0 : pendingModel.size, ", but your system has", ' ', formatBytes(usableMemoryBytes(systemMemory)), " of memory available to run it. It may run very slowly or fail to load. Download anyway?"] })] }), jsxs(AlertDialogFooter, { children: [jsx(AlertDialogCancel, { onClick: () => setPendingModel(null), children: "Cancel" }), jsx(AlertDialogAction, { onClick: confirmPendingDownload, children: "Download anyway" })] })] }) })] }));
|
|
128001
|
+
return (jsx("div", { className: "space-y-6", children: jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between rounded-lg border px-6 py-4", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx("span", { className: "text-sm font-medium text-[#646464]", children: t('localLlmLocalLlmTab.enableLocalLlm') }), jsx(TooltipProvider, { children: jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { "aria-label": t('localLlmLocalLlmTab.moreInfoAriaLabel'), className: "hidden sm:block", children: jsx(Info$3, { className: "h-4 w-4 text-gray-400" }) }), jsx(TooltipContent, { className: "rounded-lg bg-gray-700 px-3 py-2 text-sm font-medium max-w-xs text-white shadow-sm transition-opacity duration-300 z-50", children: jsxs("div", { className: "space-y-2", children: [jsx("p", { children: t('localLlmLocalLlmTab.tooltipWorkOffline') }), (foundryStatus === null || foundryStatus === void 0 ? void 0 : foundryStatus.is_supported) && (jsx("p", { className: "text-xs text-gray-300", children: t('localLlmLocalLlmTab.tooltipFoundrySupported') }))] }) })] }) })] }), jsxs("div", { className: "flex items-center gap-2", children: [isManagerInstalling && !isUsingFoundry && (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin text-blue-500", "aria-label": t('localLlmLocalLlmTab.startingModelManagerAriaLabel') })), jsx(Switch, { checked: switchChecked, onCheckedChange: handleToggle, disabled: switchDisabled, "aria-label": t('localLlmLocalLlmTab.switchAriaLabel', {
|
|
128002
|
+
state: switchChecked
|
|
128003
|
+
? t('localLlmLocalLlmTab.switchStateEnabled')
|
|
128004
|
+
: t('localLlmLocalLlmTab.switchStateDisabled'),
|
|
128005
|
+
}), className: "cursor-pointer data-[state=checked]:bg-blue-500" })] })] }), shouldShowFoundryInstall ? (jsx("div", { className: "rounded-lg border px-6 py-4 bg-blue-50/30 dark:bg-blue-950/10", style: { borderColor: 'oklch(.922 0 0)' }, children: jsxs("div", { className: "space-y-4", children: [jsx("div", { className: "flex items-start gap-3", children: jsxs("div", { className: "flex items-center gap-2 flex-shrink-0 mt-0.5", children: [jsx(Star$1, { className: "h-5 w-5 text-blue-600 fill-blue-600" }), jsx("span", { className: "px-2 py-0.5 text-xs font-semibold bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-300 rounded-full", children: t('localLlmLocalLlmTab.preferredBadge') })] }) }), jsxs("div", { className: "flex items-start gap-3", children: [jsx(Info$3, { className: "h-5 w-5 text-blue-500 flex-shrink-0 mt-0.5" }), jsxs("div", { className: "flex-1", children: [jsx("h3", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: t('localLlmLocalLlmTab.settingUpOfflineAi') }), jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: t('localLlmLocalLlmTab.foundryInstallDescription') })] })] }), state.status === 'downloading' || state.status === 'checking' ? (jsxs("div", { className: "space-y-2", children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin text-blue-500" }), jsx("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: state.message || t('localLlmLocalLlmTab.preparingDownload') })] }), state.progress > 0 && jsx(Progress, { value: state.progress, className: "h-2" })] })) : state.status === 'error' ? (jsxs("div", { className: "space-y-2", children: [jsxs("div", { className: "flex items-center gap-2 text-red-600 dark:text-red-400", children: [jsx(CircleX, { className: "h-4 w-4" }), jsx("span", { className: "text-sm", children: state.error || t('localLlmLocalLlmTab.downloadFailed') })] }), jsx("div", { className: "flex gap-2", children: jsxs(Button$1, { onClick: onInstallFoundry, size: "sm", variant: "outline", children: [jsx(RefreshCw, { className: "h-4 w-4 mr-2" }), t('localLlmLocalLlmTab.tryAgain')] }) })] })) : (jsx("div", { className: "space-y-2", children: jsxs("div", { className: "flex items-center gap-2", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin text-blue-500" }), jsx("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: t('localLlmLocalLlmTab.startingDownload') })] }) })), jsxs("div", { className: "text-xs text-gray-500 dark:text-gray-400", children: [jsx("p", { className: "font-medium mb-1", children: t('localLlmLocalLlmTab.downloadSize') }), jsx("p", { children: t('localLlmLocalLlmTab.oneTimeSetup') })] })] }) })) : /* Requirements Table - Hidden when using Foundry Local */ !isUsingFoundry ? (jsxs(Fragment$1, { children: [(foundryStatus === null || foundryStatus === void 0 ? void 0 : foundryStatus.is_supported) && (jsx("div", { className: "rounded-lg border px-4 py-3 bg-blue-50/20 dark:bg-blue-950/10", style: { borderColor: 'oklch(.922 0 0)' }, children: jsxs("div", { className: "flex items-start gap-2", children: [jsx(Info$3, { className: "h-4 w-4 text-blue-600 flex-shrink-0 mt-0.5" }), jsxs("div", { className: "text-xs text-gray-600 dark:text-gray-400", children: [jsx("span", { className: "font-medium text-gray-900 dark:text-gray-100", children: t('localLlmLocalLlmTab.noteLabel') }), ' ', t('localLlmLocalLlmTab.foundryAlternativeNote')] })] }) })), localModelsEnabled && (jsxs("div", { className: "rounded-lg border px-6 py-4", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxs("div", { className: "flex items-center gap-3", children: [jsx(Server, { className: "h-5 w-5 text-gray-400", "aria-hidden": "true" }), jsxs("div", { children: [jsx("div", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: t('localLlmLocalLlmTab.modelManagerName') }), jsx("div", { className: "text-xs text-gray-500 dark:text-gray-400", children: t('localLlmLocalLlmTab.modelManagerDescription') })] })] }), jsx("div", { className: "flex items-center gap-2", children: managerRunning ? (jsxs(Fragment$1, { children: [jsxs("span", { className: "inline-flex items-center gap-1 px-2 py-0.5 text-xs font-medium bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300 rounded-full", children: [jsx(CircleCheckBig, { className: "h-3 w-3" }), t('localLlmLocalLlmTab.running')] }), jsx(Button$1, { onClick: onCheckStatus, variant: "ghost", size: "sm", "aria-label": t('localLlmLocalLlmTab.refreshManagerStatusAriaLabel'), children: jsx(RefreshCw, { className: "h-4 w-4" }) })] })) : (jsxs(Fragment$1, { children: [jsxs("span", { className: "inline-flex items-center gap-1 px-2 py-0.5 text-xs font-medium bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300 rounded-full", children: [jsx(LoaderCircle, { className: "h-3 w-3 animate-spin" }), t('localLlmLocalLlmTab.starting')] }), jsx(Button$1, { onClick: onCheckStatus, variant: "ghost", size: "sm", "aria-label": t('localLlmLocalLlmTab.refreshManagerStatusAriaLabel'), children: jsx(RefreshCw, { className: "h-4 w-4" }) })] })) })] }), isManagerInstalling && (jsx("div", { className: "mt-3 w-full max-w-[240px]", children: jsx(Progress, { value: state.managerInstallProgress || 0, className: "h-1.5" }) }))] }))] })) : (jsx("div", { className: "rounded-lg border px-6 py-4 bg-green-50/30 dark:bg-green-950/10", style: { borderColor: 'oklch(.922 0 0)' }, children: jsxs("div", { className: "space-y-4", children: [jsx("div", { className: "flex items-center justify-between", children: jsxs("div", { className: "flex items-center gap-3", children: [jsx(CircleCheckBig, { className: "h-8 w-8 text-green-500 flex-shrink-0" }), jsxs("div", { className: "flex-1", children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx("h3", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: t('localLlmLocalLlmTab.offlineAiReady') }), jsxs("span", { className: "inline-flex items-center gap-1 px-2 py-0.5 text-xs font-semibold bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-300 rounded-full", children: [jsx(Star$1, { className: "h-3 w-3 fill-blue-700 dark:fill-blue-300" }), t('localLlmLocalLlmTab.preferredBadge')] })] }), jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: t('localLlmLocalLlmTab.foundryReadyDescription') })] })] }) }), foundryModels.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx("label", { className: "text-xs font-medium text-gray-700 dark:text-gray-300", children: t('localLlmLocalLlmTab.selectModelLabel') }), jsxs(Select$1, { value: selectedFoundryModel || ((_b = foundryModels[0]) === null || _b === void 0 ? void 0 : _b.id), onValueChange: (value) => onSelectFoundryModel === null || onSelectFoundryModel === void 0 ? void 0 : onSelectFoundryModel(value), children: [jsx(SelectTrigger, { className: "w-full bg-gray-50 border-gray-200 dark:bg-gray-800 dark:border-gray-700", children: jsx(SelectValue, { placeholder: t('localLlmLocalLlmTab.selectModelPlaceholder') }) }), jsx(SelectContent, { children: foundryModels.map((model) => (jsx(SelectItem, { value: model.id, children: jsxs("div", { className: "flex items-center justify-between w-full gap-4", children: [jsx("span", { className: "font-medium", children: model.name || model.id }), jsxs("div", { className: "flex items-center gap-2 text-xs text-gray-500", children: [model.device && (jsx("span", { className: "px-2 py-0.5 bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300 rounded", children: model.device })), model.size && jsx("span", { children: model.size }), !model.is_downloaded && (jsx("span", { className: "px-2 py-0.5 bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-300 rounded", children: t('localLlmLocalLlmTab.notDownloaded') })), model.is_downloaded && (jsx("span", { className: "px-2 py-0.5 bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300 rounded", children: t('localLlmLocalLlmTab.downloaded') }))] })] }) }, model.id))) })] }), jsxs("div", { className: "flex flex-col gap-1", children: [jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: t('localLlmLocalLlmTab.modelsAvailable', { count: foundryModels.length }) }), selectedFoundryModel && (jsxs("div", { className: "flex items-center gap-1.5 text-xs text-green-600 dark:text-green-400", children: [jsx(CircleCheckBig, { className: "h-3.5 w-3.5" }), jsxs("span", { children: [t('localLlmLocalLlmTab.usingModelPrefix'), ' ', ((_c = foundryModels.find((m) => m.id === selectedFoundryModel)) === null || _c === void 0 ? void 0 : _c.name) ||
|
|
128006
|
+
selectedFoundryModel, ((_d = foundryModels.find((m) => m.id === selectedFoundryModel)) === null || _d === void 0 ? void 0 : _d.device) && (jsxs("span", { className: "ml-1 text-gray-500 dark:text-gray-400", children: ["(", (_e = foundryModels.find((m) => m.id === selectedFoundryModel)) === null || _e === void 0 ? void 0 : _e.device, ")"] }))] })] }))] })] })), state.status === 'downloading' && (jsxs("div", { className: "mt-4 p-4 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg", children: [jsxs("div", { className: "flex items-center gap-3", children: [jsx("div", { className: "animate-spin h-5 w-5 border-2 border-blue-600 dark:border-blue-400 border-t-transparent rounded-full" }), jsxs("div", { className: "flex-1", children: [jsx("p", { className: "text-sm font-medium text-blue-900 dark:text-blue-100", children: state.message }), state.progress > 0 && (jsx("div", { className: "mt-2 w-full bg-blue-200 dark:bg-blue-800 rounded-full h-2", children: jsx("div", { className: "bg-blue-600 dark:bg-blue-400 h-2 rounded-full transition-all duration-300", style: { width: `${state.progress}%` } }) }))] })] }), state.logs.length > 0 && (jsx("div", { className: "mt-3 max-h-32 overflow-y-auto bg-white dark:bg-gray-800 rounded border border-blue-200 dark:border-blue-700 p-2", children: state.logs.slice(-10).map((log, idx) => (jsx("div", { className: `text-xs font-mono ${log.level === 'error'
|
|
128007
|
+
? 'text-red-600 dark:text-red-400'
|
|
128008
|
+
: log.level === 'warn'
|
|
128009
|
+
? 'text-yellow-600 dark:text-yellow-400'
|
|
128010
|
+
: 'text-gray-700 dark:text-gray-300'}`, children: log.message }, idx))) }))] }))] }) }))] }) }));
|
|
128284
128011
|
}
|
|
128285
128012
|
|
|
128286
128013
|
function LocalModelsContent(props) {
|
|
@@ -128291,195 +128018,6 @@ function LocalModelsContent(props) {
|
|
|
128291
128018
|
return (jsxs("div", { className: "rounded-lg px-6 py-5 border border-gray-200 dark:border-gray-700", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsxs("div", { className: "flex items-center justify-between", children: [jsxs("div", { className: "flex items-center gap-3", children: [jsx("span", { className: "text-sm font-medium text-[#646464]", children: "Local Models" }), jsx(TooltipProvider, { children: jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { "aria-label": "More info about Local Models", className: "hidden sm:block", children: jsx(Info$3, { className: "h-4 w-4 text-gray-400" }) }), jsx(TooltipContent, { className: "rounded-lg bg-gray-700 px-3 py-2 text-sm font-medium max-w-xs text-white shadow-sm transition-opacity duration-300 z-50", children: jsx("p", { children: "Manage on-device AI models for offline use." }) })] }) })] }), jsx("button", { type: "button", onClick: () => setIsCollapsed((previous) => !previous), className: "p-1 rounded hover:bg-gray-100 dark:hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1", "aria-label": isCollapsed ? 'Expand Local Models' : 'Collapse Local Models', children: isCollapsed ? (jsx(ChevronDown, { className: "h-5 w-5 text-gray-400", "aria-hidden": "true" })) : (jsx(ChevronUp, { className: "h-5 w-5 text-gray-400", "aria-hidden": "true" })) })] }), !isCollapsed && (jsx("div", { className: "mt-4", children: jsx(LocalLLMTab, { ...props }) }))] }));
|
|
128292
128019
|
}
|
|
128293
128020
|
|
|
128294
|
-
const SYSTEM_CONTROL_ENABLED_KEY = 'ibl_system_control_enabled';
|
|
128295
|
-
/**
|
|
128296
|
-
* Whether the Computer Assistant is enabled, read from localStorage. This is a
|
|
128297
|
-
* user preference (mirrors {@link isLocalLLMEnabled}); it reflects the toggle the
|
|
128298
|
-
* user last chose, independent of whether the helper is installed yet.
|
|
128299
|
-
*/
|
|
128300
|
-
function isSystemControlEnabled() {
|
|
128301
|
-
if (typeof window === 'undefined')
|
|
128302
|
-
return false;
|
|
128303
|
-
return localStorage.getItem(SYSTEM_CONTROL_ENABLED_KEY) === 'true';
|
|
128304
|
-
}
|
|
128305
|
-
/**
|
|
128306
|
-
* Persist the Computer Assistant enabled preference to localStorage.
|
|
128307
|
-
*/
|
|
128308
|
-
function setSystemControlEnabled(enabled) {
|
|
128309
|
-
if (typeof window === 'undefined')
|
|
128310
|
-
return;
|
|
128311
|
-
localStorage.setItem(SYSTEM_CONTROL_ENABLED_KEY, String(enabled));
|
|
128312
|
-
}
|
|
128313
|
-
/** Green "done" pill. */
|
|
128314
|
-
function DonePill({ children }) {
|
|
128315
|
-
return (jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-green-100 px-2 py-0.5 text-xs font-medium text-green-800 dark:bg-green-900/30 dark:text-green-300", children: [jsx(Check, { className: "h-3 w-3" }), children] }));
|
|
128316
|
-
}
|
|
128317
|
-
/** Blue "in progress" pill. */
|
|
128318
|
-
function WorkingPill({ children }) {
|
|
128319
|
-
return (jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-blue-100 px-2 py-0.5 text-xs font-medium text-blue-800 dark:bg-blue-900/30 dark:text-blue-300", children: [jsx(LoaderCircle, { className: "h-3 w-3 animate-spin" }), children] }));
|
|
128320
|
-
}
|
|
128321
|
-
/** A single numbered step row. */
|
|
128322
|
-
function Step$2({ number, done, title, description, action, }) {
|
|
128323
|
-
return (jsxs("div", { className: "flex items-start justify-between gap-3", children: [jsxs("div", { className: "flex items-start gap-3", children: [jsx("span", { className: `flex h-6 w-6 flex-shrink-0 items-center justify-center rounded-full text-xs font-semibold ${done
|
|
128324
|
-
? 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300'
|
|
128325
|
-
: 'bg-gray-100 text-gray-500 dark:bg-gray-800 dark:text-gray-400'}`, "aria-hidden": "true", children: done ? jsx(Check, { className: "h-3.5 w-3.5" }) : number }), jsxs("div", { children: [jsx("div", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: title }), jsx("div", { className: "mt-0.5 text-xs text-gray-500 dark:text-gray-400", children: description })] })] }), jsx("div", { className: "flex-shrink-0", children: action })] }));
|
|
128326
|
-
}
|
|
128327
|
-
/**
|
|
128328
|
-
* Body of the "Computer Assistant" card: a plain-language on/off with two simple
|
|
128329
|
-
* steps — set up, then allow control — so non-technical users can follow along.
|
|
128330
|
-
* Mirrors the Local Models tab so the two cards behave the same.
|
|
128331
|
-
*/
|
|
128332
|
-
function SystemControlTab({ isAvailable, state, status, requiredSizeGb = DEFAULT_SYSTEM_CONTROL_REQUIRED_SIZE_GB, ollamaStatus, systemMemory, accessibilityPermission, onInstall, onStop, onCheckStatus, onResetState, onRequestAccessibilityPermission, onDownloadModel, }) {
|
|
128333
|
-
const isInstalling = state.status === 'installing' || (status === null || status === void 0 ? void 0 : status.installing) === true;
|
|
128334
|
-
// User preference — independent of whether the helper is installed. Always
|
|
128335
|
-
// operable so the user can turn it off again.
|
|
128336
|
-
const [isEnabled, setIsEnabled] = useState(() => isSystemControlEnabled());
|
|
128337
|
-
// The currently-selected local model (persisted by the Local Models card).
|
|
128338
|
-
// Polled so a selection change in the sibling card is reflected here without a
|
|
128339
|
-
// remount. The assistant only works well with larger models, so it's gated to
|
|
128340
|
-
// a selected model above the size threshold.
|
|
128341
|
-
const [selectedModel, setSelectedModel] = useState(() => getLocalLLMModel());
|
|
128342
|
-
// Whether "Local Models" is turned on. The assistant runs on a local model, so
|
|
128343
|
-
// it's gated off until Local Models is enabled. Polled alongside the model so a
|
|
128344
|
-
// toggle in the sibling card is reflected without a remount.
|
|
128345
|
-
const [localModelsEnabled, setLocalModelsEnabled] = useState(() => isLocalLLMEnabled());
|
|
128346
|
-
useEffect(() => {
|
|
128347
|
-
const id = setInterval(() => {
|
|
128348
|
-
setSelectedModel(getLocalLLMModel());
|
|
128349
|
-
setLocalModelsEnabled(isLocalLLMEnabled());
|
|
128350
|
-
}, 1500);
|
|
128351
|
-
return () => clearInterval(id);
|
|
128352
|
-
}, []);
|
|
128353
|
-
const localModelsOff = !localModelsEnabled;
|
|
128354
|
-
const modelTooSmall = !modelSupportsSystemControl(selectedModel, requiredSizeGb);
|
|
128355
|
-
// "Upgrade" target: the smallest catalog model that clears the size gate.
|
|
128356
|
-
const upgradeTarget = smallestSystemControlModel(requiredSizeGb);
|
|
128357
|
-
// Set while an upgrade is downloading a model, before we auto-enable.
|
|
128358
|
-
const [pendingEnableModelId, setPendingEnableModelId] = useState(null);
|
|
128359
|
-
// Model awaiting a RAM/VRAM "may be too large" confirmation before download.
|
|
128360
|
-
const [pendingCapacityModel, setPendingCapacityModel] = useState(null);
|
|
128361
|
-
const isUpgrading = pendingEnableModelId !== null;
|
|
128362
|
-
const managerRunning = (status === null || status === void 0 ? void 0 : status.running) === true;
|
|
128363
|
-
// Steps are shown whenever the toggle is on (or mid-setup), so the user always
|
|
128364
|
-
// gets feedback for their choice.
|
|
128365
|
-
const managerEnabled = isEnabled || isInstalling;
|
|
128366
|
-
// Permission is known (macOS + plugin wired) and granted.
|
|
128367
|
-
const permissionKnown = typeof accessibilityPermission === 'boolean';
|
|
128368
|
-
const permissionGranted = accessibilityPermission === true;
|
|
128369
|
-
const allSet = managerRunning && (!permissionKnown || permissionGranted);
|
|
128370
|
-
// Keep the app-facing preference flag in sync with the toggle.
|
|
128371
|
-
useEffect(() => {
|
|
128372
|
-
setSystemControlEnabled(isEnabled);
|
|
128373
|
-
}, [isEnabled]);
|
|
128374
|
-
// While enabled but not yet running, keep polling so the step flips to "Ready"
|
|
128375
|
-
// as soon as the host reports the helper is up.
|
|
128376
|
-
useEffect(() => {
|
|
128377
|
-
if (!isEnabled || managerRunning)
|
|
128378
|
-
return;
|
|
128379
|
-
const id = setInterval(() => onCheckStatus(), 2500);
|
|
128380
|
-
return () => clearInterval(id);
|
|
128381
|
-
}, [isEnabled, managerRunning, onCheckStatus]);
|
|
128382
|
-
// While permission isn't granted yet, keep re-checking (the grant happens in
|
|
128383
|
-
// System Settings) so the step flips to "Allowed" on its own.
|
|
128384
|
-
useEffect(() => {
|
|
128385
|
-
if (accessibilityPermission !== false)
|
|
128386
|
-
return;
|
|
128387
|
-
const id = setInterval(() => onCheckStatus(), 2500);
|
|
128388
|
-
return () => clearInterval(id);
|
|
128389
|
-
}, [accessibilityPermission, onCheckStatus]);
|
|
128390
|
-
// After an upgrade kicks off a download, turn the assistant on once the model
|
|
128391
|
-
// finishes downloading (it shows up in the installed list).
|
|
128392
|
-
useEffect(() => {
|
|
128393
|
-
if (!pendingEnableModelId)
|
|
128394
|
-
return;
|
|
128395
|
-
if (isModelInstalled(pendingEnableModelId, ollamaStatus === null || ollamaStatus === void 0 ? void 0 : ollamaStatus.installed_models)) {
|
|
128396
|
-
setPendingEnableModelId(null);
|
|
128397
|
-
setIsEnabled(true);
|
|
128398
|
-
onInstall();
|
|
128399
|
-
}
|
|
128400
|
-
}, [pendingEnableModelId, ollamaStatus, onInstall]);
|
|
128401
|
-
if (!isAvailable) {
|
|
128402
|
-
return (jsx("div", { className: "text-sm text-gray-500 dark:text-gray-400", children: "The Computer Assistant is only available in the desktop app." }));
|
|
128403
|
-
}
|
|
128404
|
-
const handleToggle = (checked) => {
|
|
128405
|
-
// Guard: needs Local Models on and a large-enough model.
|
|
128406
|
-
if (checked && (localModelsOff || modelTooSmall))
|
|
128407
|
-
return;
|
|
128408
|
-
setIsEnabled(checked);
|
|
128409
|
-
if (checked) {
|
|
128410
|
-
if (!isInstalling)
|
|
128411
|
-
onInstall();
|
|
128412
|
-
}
|
|
128413
|
-
else {
|
|
128414
|
-
onStop === null || onStop === void 0 ? void 0 : onStop();
|
|
128415
|
-
}
|
|
128416
|
-
};
|
|
128417
|
-
// Upgrade = switch to the smallest usable model: select it, then (if it isn't
|
|
128418
|
-
// already downloaded) download it and auto-enable the assistant once it's
|
|
128419
|
-
// ready. The RAM/VRAM check is preserved via the confirm below.
|
|
128420
|
-
const runUpgrade = (model) => {
|
|
128421
|
-
setLocalLLMModel(model.id);
|
|
128422
|
-
setLocalLLMToolSupport(model.tool_support);
|
|
128423
|
-
setLocalLLMEnabled(true);
|
|
128424
|
-
setSelectedModel(model.id); // recompute the size gate immediately
|
|
128425
|
-
if (isModelInstalled(model.id, ollamaStatus === null || ollamaStatus === void 0 ? void 0 : ollamaStatus.installed_models)) {
|
|
128426
|
-
// Already downloaded → enable now.
|
|
128427
|
-
setIsEnabled(true);
|
|
128428
|
-
if (!isInstalling)
|
|
128429
|
-
onInstall();
|
|
128430
|
-
}
|
|
128431
|
-
else {
|
|
128432
|
-
// Not downloaded → download, then auto-enable when it lands (effect above).
|
|
128433
|
-
setPendingEnableModelId(model.id);
|
|
128434
|
-
onDownloadModel === null || onDownloadModel === void 0 ? void 0 : onDownloadModel(model.id);
|
|
128435
|
-
}
|
|
128436
|
-
};
|
|
128437
|
-
const handleUpgrade = () => {
|
|
128438
|
-
if (!upgradeTarget)
|
|
128439
|
-
return;
|
|
128440
|
-
// Keep the RAM/VRAM check: confirm before pulling a model that may not fit.
|
|
128441
|
-
if (modelExceedsCapacity(upgradeTarget, systemMemory)) {
|
|
128442
|
-
setPendingCapacityModel(upgradeTarget);
|
|
128443
|
-
return;
|
|
128444
|
-
}
|
|
128445
|
-
runUpgrade(upgradeTarget);
|
|
128446
|
-
};
|
|
128447
|
-
const switchChecked = isEnabled;
|
|
128448
|
-
const switchDisabled = isInstalling ||
|
|
128449
|
-
state.status === 'checking' ||
|
|
128450
|
-
((localModelsOff || modelTooSmall) && !isEnabled);
|
|
128451
|
-
return (jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between gap-4 rounded-lg border px-6 py-4", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsxs("div", { children: [jsx("div", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: "Let your assistant control this computer" }), jsx("div", { className: "mt-0.5 text-xs text-gray-500 dark:text-gray-400", children: "It can click, type, and open apps to do tasks for you. You stay in control and can turn this off anytime." })] }), jsxs("div", { className: "flex flex-shrink-0 items-center gap-2", children: [isInstalling && (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin text-blue-500", "aria-label": "Setting up" })), jsx(Switch, { checked: switchChecked, onCheckedChange: handleToggle, disabled: switchDisabled, "aria-label": "Let your assistant control this computer", className: "cursor-pointer data-[state=checked]:bg-blue-500" })] })] }), localModelsOff && (jsxs("div", { className: "flex items-start gap-2 rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 dark:border-amber-900/40 dark:bg-amber-900/10", children: [jsx(Info$3, { className: "mt-0.5 h-4 w-4 flex-shrink-0 text-amber-600", "aria-hidden": "true" }), jsx("p", { className: "text-xs text-amber-800 dark:text-amber-300", children: "Turn on \u201CLocal Models\u201D above first \u2014 the Computer Assistant uses a local AI model to do its work." })] })), !localModelsOff && modelTooSmall && (jsxs("div", { className: "flex items-start gap-2 rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 dark:border-amber-900/40 dark:bg-amber-900/10", children: [jsx(Info$3, { className: "mt-0.5 h-4 w-4 flex-shrink-0 text-amber-600", "aria-hidden": "true" }), jsxs("div", { className: "flex-1", children: [jsxs("p", { className: "text-xs text-amber-800 dark:text-amber-300", children: ["Your current AI model is too small for this.", ' ', upgradeTarget && onDownloadModel
|
|
128452
|
-
? `Upgrade to ${upgradeTarget.name} (${upgradeTarget.size}) to use it.`
|
|
128453
|
-
: 'Pick a larger one under “Local Models” above, then come back.'] }), upgradeTarget && onDownloadModel && (jsx(Button$1, { onClick: handleUpgrade, size: "sm", className: "mt-2", disabled: isUpgrading, "aria-label": `Upgrade to ${upgradeTarget.name}`, children: isUpgrading ? (jsxs(Fragment$1, { children: [jsx(LoaderCircle, { className: "mr-2 h-4 w-4 animate-spin" }), "Upgrading\u2026"] })) : (jsxs(Fragment$1, { children: [jsx(CircleArrowUp, { className: "mr-2 h-4 w-4" }), "Upgrade to ", upgradeTarget.name] })) }))] })] })), isUpgrading && !modelTooSmall && (jsxs("div", { className: "flex items-start gap-2 rounded-lg border px-4 py-3", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(LoaderCircle, { className: "mt-0.5 h-4 w-4 flex-shrink-0 animate-spin text-blue-500", "aria-hidden": "true" }), jsx("p", { className: "text-xs text-gray-600 dark:text-gray-300", children: "Downloading your new model\u2026 it\u2019ll turn on automatically when it\u2019s ready. You can watch progress under \u201CLocal Models\u201D above." })] })), managerEnabled && (jsxs("div", { className: "space-y-4 rounded-lg border px-6 py-5", style: { borderColor: 'oklch(.922 0 0)' }, children: [allSet ? (jsxs("div", { className: "flex items-start gap-2", children: [jsx(Check, { className: "mt-0.5 h-4 w-4 flex-shrink-0 text-green-600", "aria-hidden": "true" }), jsx("p", { className: "text-sm text-gray-700 dark:text-gray-300", children: "You\u2019re all set \u2014 your assistant can now help out on this computer." })] })) : (jsx("div", { className: "text-xs font-medium uppercase tracking-wide text-gray-400", children: "A couple of quick steps" })), jsx(Step$2, { number: 1, done: managerRunning, title: "Set up your assistant", description: "A quick, one-time setup so it can work on this computer.", action: managerRunning ? (jsx(DonePill, { children: "Ready" })) : (jsx(WorkingPill, { children: isInstalling ? 'Setting up…' : 'Starting…' })) }), (state.status === 'installing' || state.status === 'checking') && state.progress > 0 && (jsx(Progress, { value: state.progress, className: "h-1.5" })), permissionKnown && (jsx(Step$2, { number: 2, done: permissionGranted, title: "Allow it to control the computer", description: "Your Mac will ask you to confirm. This lets your assistant move the mouse and type for you.", action: permissionGranted ? (jsx(DonePill, { children: "Allowed" })) : onRequestAccessibilityPermission ? (jsx(Button$1, { onClick: onRequestAccessibilityPermission, size: "sm", "aria-label": "Allow your assistant to control the computer", children: "Allow" })) : (jsx("span", { className: "inline-flex items-center rounded-full bg-amber-100 px-2 py-0.5 text-xs font-medium text-amber-800 dark:bg-amber-900/30 dark:text-amber-300", children: "Needed" })) }))] })), state.status === 'error' && (jsxs("div", { className: "rounded-lg border border-red-200 bg-red-50 px-4 py-3 dark:border-red-900/40 dark:bg-red-900/10", children: [jsxs("div", { className: "flex items-center gap-2 text-sm text-red-700 dark:text-red-300", children: [jsx(CircleX, { className: "h-4 w-4 flex-shrink-0" }), jsx("span", { children: "Something went wrong while setting up. Please try again." })] }), jsxs(Button$1, { onClick: () => {
|
|
128454
|
-
onResetState();
|
|
128455
|
-
onInstall();
|
|
128456
|
-
}, size: "sm", variant: "outline", className: "mt-3", children: [jsx(RefreshCw, { className: "mr-2 h-4 w-4" }), "Try again"] })] })), jsx(AlertDialog, { open: pendingCapacityModel !== null, onOpenChange: (open) => {
|
|
128457
|
-
if (!open)
|
|
128458
|
-
setPendingCapacityModel(null);
|
|
128459
|
-
}, children: jsxs(AlertDialogContent, { children: [jsxs(AlertDialogHeader, { children: [jsx(AlertDialogTitle, { children: "This model may be large for your computer" }), jsxs(AlertDialogDescription, { children: [pendingCapacityModel === null || pendingCapacityModel === void 0 ? void 0 : pendingCapacityModel.name, " (", pendingCapacityModel === null || pendingCapacityModel === void 0 ? void 0 : pendingCapacityModel.size, ") may be more than your computer\u2019s memory can handle, so it could run slowly or fail to load. Download and use it anyway?"] })] }), jsxs(AlertDialogFooter, { children: [jsx(AlertDialogCancel, { children: "Cancel" }), jsx(AlertDialogAction, { onClick: () => {
|
|
128460
|
-
const model = pendingCapacityModel;
|
|
128461
|
-
setPendingCapacityModel(null);
|
|
128462
|
-
if (model)
|
|
128463
|
-
runUpgrade(model);
|
|
128464
|
-
}, children: "Download anyway" })] })] }) })] }));
|
|
128465
|
-
}
|
|
128466
|
-
|
|
128467
|
-
/**
|
|
128468
|
-
* Collapsible "System Control" card for the UserProfile → Advanced section.
|
|
128469
|
-
* Mirrors {@link LocalModelsContent}: a purely presentational, titled,
|
|
128470
|
-
* collapsible container whose body is the {@link SystemControlTab}. Availability
|
|
128471
|
-
* and handlers are threaded in (see UserProfileDropdown, which falls back to
|
|
128472
|
-
* {@link useGhostOs} when the host doesn't supply them). Renders nothing outside
|
|
128473
|
-
* the desktop app.
|
|
128474
|
-
*/
|
|
128475
|
-
function SystemControlContent(props) {
|
|
128476
|
-
const [isCollapsed, setIsCollapsed] = useState(true);
|
|
128477
|
-
if (!props.isAvailable) {
|
|
128478
|
-
return null;
|
|
128479
|
-
}
|
|
128480
|
-
return (jsxs("div", { className: "rounded-lg px-6 py-5 border border-gray-200 dark:border-gray-700", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsxs("div", { className: "flex items-center justify-between", children: [jsxs("div", { className: "flex items-center gap-3", children: [jsx("span", { className: "text-sm font-medium text-[#646464]", children: "Computer Assistant" }), jsx(TooltipProvider, { children: jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { "aria-label": "More info about the Computer Assistant", className: "hidden sm:block", children: jsx(Info$3, { className: "h-4 w-4 text-gray-400" }) }), jsx(TooltipContent, { className: "rounded-lg bg-gray-700 px-3 py-2 text-sm font-medium max-w-xs text-white shadow-sm transition-opacity duration-300 z-50", children: jsx("p", { children: "Let your assistant do things on your computer \u2014 click, type, and open apps. You stay in control and can turn it off anytime." }) })] }) })] }), jsx("button", { type: "button", onClick: () => setIsCollapsed((previous) => !previous), className: "p-1 rounded hover:bg-gray-100 dark:hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1", "aria-label": isCollapsed ? 'Expand Computer Assistant' : 'Collapse Computer Assistant', children: isCollapsed ? (jsx(ChevronDown, { className: "h-5 w-5 text-gray-400", "aria-hidden": "true" })) : (jsx(ChevronUp, { className: "h-5 w-5 text-gray-400", "aria-hidden": "true" })) })] }), !isCollapsed && (jsx("div", { className: "mt-4", children: jsx(SystemControlTab, { ...props }) }))] }));
|
|
128481
|
-
}
|
|
128482
|
-
|
|
128483
128021
|
// src/primitive.tsx
|
|
128484
128022
|
var NODES = [
|
|
128485
128023
|
"a",
|
|
@@ -176503,6 +176041,26 @@ function ChatPrivacyTab({ org, username }) {
|
|
|
176503
176041
|
}) })] }));
|
|
176504
176042
|
}
|
|
176505
176043
|
|
|
176044
|
+
const COWORK_ENABLED_KEY = 'ibl_cowork_enabled';
|
|
176045
|
+
/**
|
|
176046
|
+
* Whether Cowork is enabled, read from localStorage. This is a user preference
|
|
176047
|
+
* (mirrors isLocalLLMEnabled); it reflects the toggle the user last chose,
|
|
176048
|
+
* independent of whether the assistant is installed yet.
|
|
176049
|
+
*/
|
|
176050
|
+
function isCoworkEnabled() {
|
|
176051
|
+
if (typeof window === 'undefined')
|
|
176052
|
+
return false;
|
|
176053
|
+
return localStorage.getItem(COWORK_ENABLED_KEY) === 'true';
|
|
176054
|
+
}
|
|
176055
|
+
/**
|
|
176056
|
+
* Persist the Cowork enabled preference to localStorage.
|
|
176057
|
+
*/
|
|
176058
|
+
function setCoworkEnabled(enabled) {
|
|
176059
|
+
if (typeof window === 'undefined')
|
|
176060
|
+
return;
|
|
176061
|
+
localStorage.setItem(COWORK_ENABLED_KEY, String(enabled));
|
|
176062
|
+
}
|
|
176063
|
+
|
|
176506
176064
|
const renderLucideIcon = (Icon) => function RenderedIcon(props) {
|
|
176507
176065
|
return jsx(Icon, { ...props });
|
|
176508
176066
|
};
|
|
@@ -176529,7 +176087,7 @@ const TAB_DESC_PREVIEW_KEYS = {
|
|
|
176529
176087
|
memory: 'descMemoryPreview',
|
|
176530
176088
|
privacy: 'descPrivacyPreview',
|
|
176531
176089
|
};
|
|
176532
|
-
function Profile({ tenant, username, tenants, onClose, customization = {}, isAdmin = false, targetTab = 'basic', onAccountDeleted, enableMemoryTab = false, localLLMProps,
|
|
176090
|
+
function Profile({ tenant, username, tenants, onClose, customization = {}, isAdmin = false, targetTab = 'basic', onAccountDeleted, enableMemoryTab = false, localLLMProps, currentSPA = '', }) {
|
|
176533
176091
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
176534
176092
|
const t = useT();
|
|
176535
176093
|
const { data: memsearchStatus, isError: isMemsearchStatusError } = useGetMemsearchStatusQuery({ org: tenant, userId: username }, { skip: !enableMemoryTab });
|
|
@@ -176606,9 +176164,8 @@ function Profile({ tenant, username, tenants, onClose, customization = {}, isAdm
|
|
|
176606
176164
|
]
|
|
176607
176165
|
: []),
|
|
176608
176166
|
];
|
|
176609
|
-
// Add Advanced tab only when in Tauri app (Local Models
|
|
176610
|
-
|
|
176611
|
-
const isAdvancedAvailable = (localLLMProps === null || localLLMProps === void 0 ? void 0 : localLLMProps.isAvailable) === true || (systemControlProps === null || systemControlProps === void 0 ? void 0 : systemControlProps.isAvailable) === true;
|
|
176167
|
+
// Add Advanced tab only when in Tauri app (Local Models is provided and available)
|
|
176168
|
+
const isAdvancedAvailable = (localLLMProps === null || localLLMProps === void 0 ? void 0 : localLLMProps.isAvailable) === true;
|
|
176612
176169
|
const TABS = isAdvancedAvailable
|
|
176613
176170
|
? [
|
|
176614
176171
|
...baseTabs,
|
|
@@ -176774,7 +176331,7 @@ function Profile({ tenant, username, tenants, onClose, customization = {}, isAdm
|
|
|
176774
176331
|
var _a;
|
|
176775
176332
|
return (jsxs(Fragment$1, { children: [jsxs("div", { className: "relative mb-0", children: [jsx("div", { className: "absolute inset-y-0 left-4 flex items-center pointer-events-none", "aria-hidden": "true", children: jsx("div", { className: "bg-black text-white rounded w-8 h-8 flex items-center justify-center", children: jsx("span", { className: "font-bold text-sm", children: "X" }) }) }), jsx(Input, { id: "x", className: "w-full bg-gray-50 border-gray-200 focus:ring-blue-500 focus:border-blue-500 text-base py-3 pl-16 h-10", placeholder: t('profileIndex.placeholderX'), value: field.state.value, onChange: (e) => handleSocialLinkChange(e.target.value, field.handleChange, X_URL_PREFIX), disabled: socialForm.state.isSubmitting || isReadOnly })] }), jsx("p", { className: "text-red-500 dark:text-gray-400 text-sm", role: ((_a = field.state.meta.errors) === null || _a === void 0 ? void 0 : _a.length) ? 'alert' : undefined, "aria-live": "polite", children: field.state.meta.errors })] }));
|
|
176776
176333
|
},
|
|
176777
|
-
})] })] }) })), activeTab === 'education' && (jsxs(Tabs, { value: educationSubTab, onValueChange: setEducationSubTab, className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxs(TabsList, { children: [jsx(TabsTrigger, { value: "education", children: t('profileIndex.tabEducation') }), jsx(TabsTrigger, { value: "credentials", children: t('gradebookGradebookTab.typeCredentials') }), jsx(TabsTrigger, { value: "skills", children: t('gradebookGradebookTab.typeSkills') })] }), headerAddButton] }), jsx(TabsContent, { value: "education", children: jsx(EducationTab, { org: tenant, username: username }) }), jsx(TabsContent, { value: "credentials", children: jsx(CredentialsList, { org: tenant, username: username }) }), jsx(TabsContent, { value: "skills", children: jsx(SkillsList, { org: tenant, username: username }) })] })), activeTab === 'gradebook' && jsx(GradebookTab, { org: tenant, username: username }), activeTab === 'experience' && (jsxs(Tabs, { value: experienceSubTab, onValueChange: setExperienceSubTab, className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxs(TabsList, { children: [jsx(TabsTrigger, { value: "experience", children: t('profileIndex.tabExperience') }), jsx(TabsTrigger, { value: "resume", children: t('profileIndex.tabResume') })] }), headerAddButton] }), jsx(TabsContent, { value: "experience", children: jsx(ExperienceTab, { org: tenant, username: username }) }), jsx(TabsContent, { value: "resume", children: jsx(ResumeTab, { org: tenant, username: username }) })] })), activeTab === 'purchases' && jsx(PurchasesTab, { org: tenant, username: username }), activeTab === 'memory' && jsx(MemoryTab, { org: tenant, username: username }), activeTab === 'privacy' && jsx(ChatPrivacyTab, { org: tenant, username: username }), !isReadOnly && activeTab === 'security' && (jsx(Security, { app: currentSPA || '', email: (userMetadata === null || userMetadata === void 0 ? void 0 : userMetadata.email) || '', platformKey: tenant, onAccountDeleted: onAccountDeleted })), activeTab === 'advanced' &&
|
|
176334
|
+
})] })] }) })), activeTab === 'education' && (jsxs(Tabs, { value: educationSubTab, onValueChange: setEducationSubTab, className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxs(TabsList, { children: [jsx(TabsTrigger, { value: "education", children: t('profileIndex.tabEducation') }), jsx(TabsTrigger, { value: "credentials", children: t('gradebookGradebookTab.typeCredentials') }), jsx(TabsTrigger, { value: "skills", children: t('gradebookGradebookTab.typeSkills') })] }), headerAddButton] }), jsx(TabsContent, { value: "education", children: jsx(EducationTab, { org: tenant, username: username }) }), jsx(TabsContent, { value: "credentials", children: jsx(CredentialsList, { org: tenant, username: username }) }), jsx(TabsContent, { value: "skills", children: jsx(SkillsList, { org: tenant, username: username }) })] })), activeTab === 'gradebook' && jsx(GradebookTab, { org: tenant, username: username }), activeTab === 'experience' && (jsxs(Tabs, { value: experienceSubTab, onValueChange: setExperienceSubTab, className: "space-y-4", children: [jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxs(TabsList, { children: [jsx(TabsTrigger, { value: "experience", children: t('profileIndex.tabExperience') }), jsx(TabsTrigger, { value: "resume", children: t('profileIndex.tabResume') })] }), headerAddButton] }), jsx(TabsContent, { value: "experience", children: jsx(ExperienceTab, { org: tenant, username: username }) }), jsx(TabsContent, { value: "resume", children: jsx(ResumeTab, { org: tenant, username: username }) })] })), activeTab === 'purchases' && jsx(PurchasesTab, { org: tenant, username: username }), activeTab === 'memory' && jsx(MemoryTab, { org: tenant, username: username }), activeTab === 'privacy' && jsx(ChatPrivacyTab, { org: tenant, username: username }), !isReadOnly && activeTab === 'security' && (jsx(Security, { app: currentSPA || '', email: (userMetadata === null || userMetadata === void 0 ? void 0 : userMetadata.email) || '', platformKey: tenant, onAccountDeleted: onAccountDeleted })), activeTab === 'advanced' && localLLMProps && (jsx("div", { className: "space-y-6", children: jsx(LocalModelsContent, { isAvailable: localLLMProps.isAvailable, state: localLLMProps.state, ollamaStatus: localLLMProps.ollamaStatus, systemMemory: localLLMProps.systemMemory, isUsingFoundry: localLLMProps.isUsingFoundry, foundryModels: localLLMProps.foundryModels, selectedFoundryModel: localLLMProps.selectedFoundryModel, foundryStatus: localLLMProps.foundryStatus, onStartDownload: localLLMProps.onStartDownload, onCancelDownload: localLLMProps.onCancelDownload, onInstallOllama: localLLMProps.onInstallOllama, onStopManager: localLLMProps.onStopManager, onInstallFoundry: localLLMProps.onInstallFoundry, onCheckStatus: localLLMProps.onCheckStatus, onResetState: localLLMProps.onResetState, onSelectFoundryModel: localLLMProps.onSelectFoundryModel }) }))] }), !isReadOnly && ['basic', 'social'].includes(activeTab) && (jsx("div", { className: "flex-shrink-0 border-t border-gray-200 p-6 bg-white dark:bg-gray-900", children: jsxs("div", { className: "flex justify-end gap-3", children: [jsx(Button$1, { onClick: onClose, variant: "outline", children: t('profileIndex.buttonCancel') }), jsx(Button$1, { onClick: () => {
|
|
176778
176335
|
if (activeTab === 'basic') {
|
|
176779
176336
|
basicForm.handleSubmit();
|
|
176780
176337
|
}
|
|
@@ -178253,11 +177810,11 @@ var PopoverAnchor$1 = React.forwardRef(
|
|
|
178253
177810
|
}
|
|
178254
177811
|
);
|
|
178255
177812
|
PopoverAnchor$1.displayName = ANCHOR_NAME$1;
|
|
178256
|
-
var TRIGGER_NAME$
|
|
177813
|
+
var TRIGGER_NAME$3 = "PopoverTrigger";
|
|
178257
177814
|
var PopoverTrigger$1 = React.forwardRef(
|
|
178258
177815
|
(props, forwardedRef) => {
|
|
178259
177816
|
const { __scopePopover, ...triggerProps } = props;
|
|
178260
|
-
const context = usePopoverContext(TRIGGER_NAME$
|
|
177817
|
+
const context = usePopoverContext(TRIGGER_NAME$3, __scopePopover);
|
|
178261
177818
|
const popperScope = usePopperScope$1(__scopePopover);
|
|
178262
177819
|
const composedTriggerRef = useComposedRefs$1(forwardedRef, context.triggerRef);
|
|
178263
177820
|
const trigger = /* @__PURE__ */ jsx(
|
|
@@ -178276,31 +177833,31 @@ var PopoverTrigger$1 = React.forwardRef(
|
|
|
178276
177833
|
return context.hasCustomAnchor ? trigger : /* @__PURE__ */ jsx(Anchor$3, { asChild: true, ...popperScope, children: trigger });
|
|
178277
177834
|
}
|
|
178278
177835
|
);
|
|
178279
|
-
PopoverTrigger$1.displayName = TRIGGER_NAME$
|
|
178280
|
-
var PORTAL_NAME$
|
|
178281
|
-
var [PortalProvider$1, usePortalContext$1] = createPopoverContext(PORTAL_NAME$
|
|
177836
|
+
PopoverTrigger$1.displayName = TRIGGER_NAME$3;
|
|
177837
|
+
var PORTAL_NAME$2 = "PopoverPortal";
|
|
177838
|
+
var [PortalProvider$1, usePortalContext$1] = createPopoverContext(PORTAL_NAME$2, {
|
|
178282
177839
|
forceMount: void 0
|
|
178283
177840
|
});
|
|
178284
177841
|
var PopoverPortal = (props) => {
|
|
178285
177842
|
const { __scopePopover, forceMount, children, container } = props;
|
|
178286
|
-
const context = usePopoverContext(PORTAL_NAME$
|
|
177843
|
+
const context = usePopoverContext(PORTAL_NAME$2, __scopePopover);
|
|
178287
177844
|
return /* @__PURE__ */ jsx(PortalProvider$1, { scope: __scopePopover, forceMount, children: /* @__PURE__ */ jsx(Presence$3, { present: forceMount || context.open, children: /* @__PURE__ */ jsx(Portal$7, { asChild: true, container, children }) }) });
|
|
178288
177845
|
};
|
|
178289
|
-
PopoverPortal.displayName = PORTAL_NAME$
|
|
178290
|
-
var CONTENT_NAME$
|
|
177846
|
+
PopoverPortal.displayName = PORTAL_NAME$2;
|
|
177847
|
+
var CONTENT_NAME$4 = "PopoverContent";
|
|
178291
177848
|
var PopoverContent$1 = React.forwardRef(
|
|
178292
177849
|
(props, forwardedRef) => {
|
|
178293
|
-
const portalContext = usePortalContext$1(CONTENT_NAME$
|
|
177850
|
+
const portalContext = usePortalContext$1(CONTENT_NAME$4, props.__scopePopover);
|
|
178294
177851
|
const { forceMount = portalContext.forceMount, ...contentProps } = props;
|
|
178295
|
-
const context = usePopoverContext(CONTENT_NAME$
|
|
177852
|
+
const context = usePopoverContext(CONTENT_NAME$4, props.__scopePopover);
|
|
178296
177853
|
return /* @__PURE__ */ jsx(Presence$3, { present: forceMount || context.open, children: context.modal ? /* @__PURE__ */ jsx(PopoverContentModal, { ...contentProps, ref: forwardedRef }) : /* @__PURE__ */ jsx(PopoverContentNonModal, { ...contentProps, ref: forwardedRef }) });
|
|
178297
177854
|
}
|
|
178298
177855
|
);
|
|
178299
|
-
PopoverContent$1.displayName = CONTENT_NAME$
|
|
177856
|
+
PopoverContent$1.displayName = CONTENT_NAME$4;
|
|
178300
177857
|
var Slot = createSlot$1("PopoverContent.RemoveScroll");
|
|
178301
177858
|
var PopoverContentModal = React.forwardRef(
|
|
178302
177859
|
(props, forwardedRef) => {
|
|
178303
|
-
const context = usePopoverContext(CONTENT_NAME$
|
|
177860
|
+
const context = usePopoverContext(CONTENT_NAME$4, props.__scopePopover);
|
|
178304
177861
|
const contentRef = React.useRef(null);
|
|
178305
177862
|
const composedRefs = useComposedRefs$1(forwardedRef, contentRef);
|
|
178306
177863
|
const isRightClickOutsideRef = React.useRef(false);
|
|
@@ -178340,7 +177897,7 @@ var PopoverContentModal = React.forwardRef(
|
|
|
178340
177897
|
);
|
|
178341
177898
|
var PopoverContentNonModal = React.forwardRef(
|
|
178342
177899
|
(props, forwardedRef) => {
|
|
178343
|
-
const context = usePopoverContext(CONTENT_NAME$
|
|
177900
|
+
const context = usePopoverContext(CONTENT_NAME$4, props.__scopePopover);
|
|
178344
177901
|
const hasInteractedOutsideRef = React.useRef(false);
|
|
178345
177902
|
const hasPointerDownOutsideRef = React.useRef(false);
|
|
178346
177903
|
return /* @__PURE__ */ jsx(
|
|
@@ -178392,7 +177949,7 @@ var PopoverContentImpl = React.forwardRef(
|
|
|
178392
177949
|
onInteractOutside,
|
|
178393
177950
|
...contentProps
|
|
178394
177951
|
} = props;
|
|
178395
|
-
const context = usePopoverContext(CONTENT_NAME$
|
|
177952
|
+
const context = usePopoverContext(CONTENT_NAME$4, __scopePopover);
|
|
178396
177953
|
const popperScope = usePopperScope$1(__scopePopover);
|
|
178397
177954
|
useFocusGuards();
|
|
178398
177955
|
return /* @__PURE__ */ jsx(
|
|
@@ -178470,26 +178027,26 @@ PopoverArrow.displayName = ARROW_NAME$2;
|
|
|
178470
178027
|
function getState$2(open) {
|
|
178471
178028
|
return open ? "open" : "closed";
|
|
178472
178029
|
}
|
|
178473
|
-
var Root2$
|
|
178030
|
+
var Root2$4 = Popover$1;
|
|
178474
178031
|
var Anchor2 = PopoverAnchor$1;
|
|
178475
178032
|
var Trigger$1 = PopoverTrigger$1;
|
|
178476
178033
|
var Portal$1 = PopoverPortal;
|
|
178477
|
-
var Content2$
|
|
178034
|
+
var Content2$2 = PopoverContent$1;
|
|
178478
178035
|
|
|
178479
|
-
const Popover = Root2$
|
|
178036
|
+
const Popover = Root2$4;
|
|
178480
178037
|
const PopoverTrigger = Trigger$1;
|
|
178481
178038
|
const PopoverAnchor = Anchor2;
|
|
178482
178039
|
const PopoverContent = React.forwardRef(({ className, align = 'center', sideOffset = 4, portalled = true, container, ...props }, ref) => {
|
|
178483
178040
|
var _a;
|
|
178484
178041
|
const portalContainer = useFloatingPortalContainer();
|
|
178485
178042
|
const resolvedContainer = (_a = container !== null && container !== void 0 ? container : portalContainer) !== null && _a !== void 0 ? _a : undefined;
|
|
178486
|
-
const content = (jsx(Content2$
|
|
178043
|
+
const content = (jsx(Content2$2, { ref: ref, "data-iblai-dialog-interaction-layer": true, align: align, sideOffset: sideOffset, className: cn('bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 rounded-md border p-4 shadow-md outline-none', className), ...props }));
|
|
178487
178044
|
if (!portalled) {
|
|
178488
178045
|
return content;
|
|
178489
178046
|
}
|
|
178490
178047
|
return jsx(Portal$1, { container: resolvedContainer, children: content });
|
|
178491
178048
|
});
|
|
178492
|
-
PopoverContent.displayName = Content2$
|
|
178049
|
+
PopoverContent.displayName = Content2$2.displayName;
|
|
178493
178050
|
|
|
178494
178051
|
function UsersTab({ tenant, onInviteClick, currentSpa, showGradebookTab = false, }) {
|
|
178495
178052
|
const t = useT();
|
|
@@ -180371,11 +179928,11 @@ var Collapsible$1 = React.forwardRef(
|
|
|
180371
179928
|
}
|
|
180372
179929
|
);
|
|
180373
179930
|
Collapsible$1.displayName = COLLAPSIBLE_NAME;
|
|
180374
|
-
var TRIGGER_NAME$
|
|
179931
|
+
var TRIGGER_NAME$2 = "CollapsibleTrigger";
|
|
180375
179932
|
var CollapsibleTrigger$1 = React.forwardRef(
|
|
180376
179933
|
(props, forwardedRef) => {
|
|
180377
179934
|
const { __scopeCollapsible, ...triggerProps } = props;
|
|
180378
|
-
const context = useCollapsibleContext(TRIGGER_NAME$
|
|
179935
|
+
const context = useCollapsibleContext(TRIGGER_NAME$2, __scopeCollapsible);
|
|
180379
179936
|
return /* @__PURE__ */ jsx(
|
|
180380
179937
|
Primitive$2.button,
|
|
180381
179938
|
{
|
|
@@ -180392,19 +179949,19 @@ var CollapsibleTrigger$1 = React.forwardRef(
|
|
|
180392
179949
|
);
|
|
180393
179950
|
}
|
|
180394
179951
|
);
|
|
180395
|
-
CollapsibleTrigger$1.displayName = TRIGGER_NAME$
|
|
180396
|
-
var CONTENT_NAME$
|
|
179952
|
+
CollapsibleTrigger$1.displayName = TRIGGER_NAME$2;
|
|
179953
|
+
var CONTENT_NAME$3 = "CollapsibleContent";
|
|
180397
179954
|
var CollapsibleContent$1 = React.forwardRef(
|
|
180398
179955
|
(props, forwardedRef) => {
|
|
180399
179956
|
const { forceMount, ...contentProps } = props;
|
|
180400
|
-
const context = useCollapsibleContext(CONTENT_NAME$
|
|
179957
|
+
const context = useCollapsibleContext(CONTENT_NAME$3, props.__scopeCollapsible);
|
|
180401
179958
|
return /* @__PURE__ */ jsx(Presence$2, { present: forceMount || context.open, children: ({ present }) => /* @__PURE__ */ jsx(CollapsibleContentImpl, { ...contentProps, ref: forwardedRef, present }) });
|
|
180402
179959
|
}
|
|
180403
179960
|
);
|
|
180404
|
-
CollapsibleContent$1.displayName = CONTENT_NAME$
|
|
179961
|
+
CollapsibleContent$1.displayName = CONTENT_NAME$3;
|
|
180405
179962
|
var CollapsibleContentImpl = React.forwardRef((props, forwardedRef) => {
|
|
180406
179963
|
const { __scopeCollapsible, present, children, ...contentProps } = props;
|
|
180407
|
-
const context = useCollapsibleContext(CONTENT_NAME$
|
|
179964
|
+
const context = useCollapsibleContext(CONTENT_NAME$3, __scopeCollapsible);
|
|
180408
179965
|
const [isPresent, setIsPresent] = React.useState(present);
|
|
180409
179966
|
const ref = React.useRef(null);
|
|
180410
179967
|
const composedRefs = useComposedRefs$1(forwardedRef, ref);
|
|
@@ -203640,7 +203197,7 @@ var joinTextblockForward = () => ({ state, dispatch }) => {
|
|
|
203640
203197
|
};
|
|
203641
203198
|
|
|
203642
203199
|
// src/utilities/isMacOS.ts
|
|
203643
|
-
function isMacOS() {
|
|
203200
|
+
function isMacOS$1() {
|
|
203644
203201
|
return typeof navigator !== "undefined" ? /Mac/.test(navigator.platform) : false;
|
|
203645
203202
|
}
|
|
203646
203203
|
|
|
@@ -203666,7 +203223,7 @@ function normalizeKeyName(name) {
|
|
|
203666
203223
|
} else if (/^s(hift)?$/i.test(mod)) {
|
|
203667
203224
|
shift = true;
|
|
203668
203225
|
} else if (/^mod$/i.test(mod)) {
|
|
203669
|
-
if (isiOS() || isMacOS()) {
|
|
203226
|
+
if (isiOS() || isMacOS$1()) {
|
|
203670
203227
|
meta = true;
|
|
203671
203228
|
} else {
|
|
203672
203229
|
ctrl = true;
|
|
@@ -206643,7 +206200,7 @@ var Keymap = Extension.create({
|
|
|
206643
206200
|
"Ctrl-a": () => this.editor.commands.selectTextblockStart(),
|
|
206644
206201
|
"Ctrl-e": () => this.editor.commands.selectTextblockEnd()
|
|
206645
206202
|
};
|
|
206646
|
-
if (isiOS() || isMacOS()) {
|
|
206203
|
+
if (isiOS() || isMacOS$1()) {
|
|
206647
206204
|
return macKeymap;
|
|
206648
206205
|
}
|
|
206649
206206
|
return pcKeymap;
|
|
@@ -217172,17 +216729,184 @@ var RadioGroupIndicator = React.forwardRef(
|
|
|
217172
216729
|
}
|
|
217173
216730
|
);
|
|
217174
216731
|
RadioGroupIndicator.displayName = INDICATOR_NAME2;
|
|
217175
|
-
var Root2$
|
|
216732
|
+
var Root2$3 = RadioGroup$1;
|
|
217176
216733
|
var Item2 = RadioGroupItem$1;
|
|
217177
216734
|
var Indicator = RadioGroupIndicator;
|
|
217178
216735
|
|
|
217179
216736
|
function RadioGroup({ className, ...props }) {
|
|
217180
|
-
return (jsx(Root2$
|
|
216737
|
+
return (jsx(Root2$3, { "data-slot": "radio-group", className: cn('grid gap-3', className), ...props }));
|
|
217181
216738
|
}
|
|
217182
216739
|
function RadioGroupItem({ className, ...props }) {
|
|
217183
216740
|
return (jsx(Item2, { "data-slot": "radio-group-item", className: cn('border-input text-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 aspect-square size-4 shrink-0 rounded-full border shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50', className), ...props, children: jsx(Indicator, { "data-slot": "radio-group-indicator", className: "relative flex items-center justify-center", children: jsx(Circle, { className: "fill-primary absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2" }) }) }));
|
|
217184
216741
|
}
|
|
217185
216742
|
|
|
216743
|
+
var SLOTTABLE_IDENTIFIER = Symbol("radix.slottable");
|
|
216744
|
+
// @__NO_SIDE_EFFECTS__
|
|
216745
|
+
function createSlottable(ownerName) {
|
|
216746
|
+
const Slottable2 = ({ children }) => {
|
|
216747
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children });
|
|
216748
|
+
};
|
|
216749
|
+
Slottable2.displayName = `${ownerName}.Slottable`;
|
|
216750
|
+
Slottable2.__radixId = SLOTTABLE_IDENTIFIER;
|
|
216751
|
+
return Slottable2;
|
|
216752
|
+
}
|
|
216753
|
+
|
|
216754
|
+
var ROOT_NAME = "AlertDialog";
|
|
216755
|
+
var [createAlertDialogContext] = createContextScope$1(ROOT_NAME, [
|
|
216756
|
+
createDialogScope
|
|
216757
|
+
]);
|
|
216758
|
+
var useDialogScope = createDialogScope();
|
|
216759
|
+
var AlertDialog$1 = (props) => {
|
|
216760
|
+
const { __scopeAlertDialog, ...alertDialogProps } = props;
|
|
216761
|
+
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
216762
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Root, { ...dialogScope, ...alertDialogProps, modal: true });
|
|
216763
|
+
};
|
|
216764
|
+
AlertDialog$1.displayName = ROOT_NAME;
|
|
216765
|
+
var TRIGGER_NAME$1 = "AlertDialogTrigger";
|
|
216766
|
+
var AlertDialogTrigger = React.forwardRef(
|
|
216767
|
+
(props, forwardedRef) => {
|
|
216768
|
+
const { __scopeAlertDialog, ...triggerProps } = props;
|
|
216769
|
+
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
216770
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Trigger, { ...dialogScope, ...triggerProps, ref: forwardedRef });
|
|
216771
|
+
}
|
|
216772
|
+
);
|
|
216773
|
+
AlertDialogTrigger.displayName = TRIGGER_NAME$1;
|
|
216774
|
+
var PORTAL_NAME$1 = "AlertDialogPortal";
|
|
216775
|
+
var AlertDialogPortal$1 = (props) => {
|
|
216776
|
+
const { __scopeAlertDialog, ...portalProps } = props;
|
|
216777
|
+
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
216778
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Portal, { ...dialogScope, ...portalProps });
|
|
216779
|
+
};
|
|
216780
|
+
AlertDialogPortal$1.displayName = PORTAL_NAME$1;
|
|
216781
|
+
var OVERLAY_NAME = "AlertDialogOverlay";
|
|
216782
|
+
var AlertDialogOverlay$1 = React.forwardRef(
|
|
216783
|
+
(props, forwardedRef) => {
|
|
216784
|
+
const { __scopeAlertDialog, ...overlayProps } = props;
|
|
216785
|
+
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
216786
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Overlay, { ...dialogScope, ...overlayProps, ref: forwardedRef });
|
|
216787
|
+
}
|
|
216788
|
+
);
|
|
216789
|
+
AlertDialogOverlay$1.displayName = OVERLAY_NAME;
|
|
216790
|
+
var CONTENT_NAME$2 = "AlertDialogContent";
|
|
216791
|
+
var [AlertDialogContentProvider, useAlertDialogContentContext] = createAlertDialogContext(CONTENT_NAME$2);
|
|
216792
|
+
var Slottable = createSlottable("AlertDialogContent");
|
|
216793
|
+
var AlertDialogContent$1 = React.forwardRef(
|
|
216794
|
+
(props, forwardedRef) => {
|
|
216795
|
+
const { __scopeAlertDialog, children, ...contentProps } = props;
|
|
216796
|
+
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
216797
|
+
const contentRef = React.useRef(null);
|
|
216798
|
+
const composedRefs = useComposedRefs$1(forwardedRef, contentRef);
|
|
216799
|
+
const cancelRef = React.useRef(null);
|
|
216800
|
+
return /* @__PURE__ */ jsx(
|
|
216801
|
+
DialogPrimitive.WarningProvider,
|
|
216802
|
+
{
|
|
216803
|
+
contentName: CONTENT_NAME$2,
|
|
216804
|
+
titleName: TITLE_NAME,
|
|
216805
|
+
docsSlug: "alert-dialog",
|
|
216806
|
+
children: /* @__PURE__ */ jsx(AlertDialogContentProvider, { scope: __scopeAlertDialog, cancelRef, children: /* @__PURE__ */ jsxs(
|
|
216807
|
+
DialogPrimitive.Content,
|
|
216808
|
+
{
|
|
216809
|
+
role: "alertdialog",
|
|
216810
|
+
...dialogScope,
|
|
216811
|
+
...contentProps,
|
|
216812
|
+
ref: composedRefs,
|
|
216813
|
+
onOpenAutoFocus: composeEventHandlers$2(contentProps.onOpenAutoFocus, (event) => {
|
|
216814
|
+
event.preventDefault();
|
|
216815
|
+
cancelRef.current?.focus({ preventScroll: true });
|
|
216816
|
+
}),
|
|
216817
|
+
onPointerDownOutside: (event) => event.preventDefault(),
|
|
216818
|
+
onInteractOutside: (event) => event.preventDefault(),
|
|
216819
|
+
children: [
|
|
216820
|
+
/* @__PURE__ */ jsx(Slottable, { children }),
|
|
216821
|
+
/* @__PURE__ */ jsx(DescriptionWarning, { contentRef })
|
|
216822
|
+
]
|
|
216823
|
+
}
|
|
216824
|
+
) })
|
|
216825
|
+
}
|
|
216826
|
+
);
|
|
216827
|
+
}
|
|
216828
|
+
);
|
|
216829
|
+
AlertDialogContent$1.displayName = CONTENT_NAME$2;
|
|
216830
|
+
var TITLE_NAME = "AlertDialogTitle";
|
|
216831
|
+
var AlertDialogTitle$1 = React.forwardRef(
|
|
216832
|
+
(props, forwardedRef) => {
|
|
216833
|
+
const { __scopeAlertDialog, ...titleProps } = props;
|
|
216834
|
+
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
216835
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Title, { ...dialogScope, ...titleProps, ref: forwardedRef });
|
|
216836
|
+
}
|
|
216837
|
+
);
|
|
216838
|
+
AlertDialogTitle$1.displayName = TITLE_NAME;
|
|
216839
|
+
var DESCRIPTION_NAME = "AlertDialogDescription";
|
|
216840
|
+
var AlertDialogDescription$1 = React.forwardRef((props, forwardedRef) => {
|
|
216841
|
+
const { __scopeAlertDialog, ...descriptionProps } = props;
|
|
216842
|
+
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
216843
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Description, { ...dialogScope, ...descriptionProps, ref: forwardedRef });
|
|
216844
|
+
});
|
|
216845
|
+
AlertDialogDescription$1.displayName = DESCRIPTION_NAME;
|
|
216846
|
+
var ACTION_NAME = "AlertDialogAction";
|
|
216847
|
+
var AlertDialogAction$1 = React.forwardRef(
|
|
216848
|
+
(props, forwardedRef) => {
|
|
216849
|
+
const { __scopeAlertDialog, ...actionProps } = props;
|
|
216850
|
+
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
216851
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Close, { ...dialogScope, ...actionProps, ref: forwardedRef });
|
|
216852
|
+
}
|
|
216853
|
+
);
|
|
216854
|
+
AlertDialogAction$1.displayName = ACTION_NAME;
|
|
216855
|
+
var CANCEL_NAME = "AlertDialogCancel";
|
|
216856
|
+
var AlertDialogCancel$1 = React.forwardRef(
|
|
216857
|
+
(props, forwardedRef) => {
|
|
216858
|
+
const { __scopeAlertDialog, ...cancelProps } = props;
|
|
216859
|
+
const { cancelRef } = useAlertDialogContentContext(CANCEL_NAME, __scopeAlertDialog);
|
|
216860
|
+
const dialogScope = useDialogScope(__scopeAlertDialog);
|
|
216861
|
+
const ref = useComposedRefs$1(forwardedRef, cancelRef);
|
|
216862
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Close, { ...dialogScope, ...cancelProps, ref });
|
|
216863
|
+
}
|
|
216864
|
+
);
|
|
216865
|
+
AlertDialogCancel$1.displayName = CANCEL_NAME;
|
|
216866
|
+
var DescriptionWarning = ({ contentRef }) => {
|
|
216867
|
+
const MESSAGE = `\`${CONTENT_NAME$2}\` requires a description for the component to be accessible for screen reader users.
|
|
216868
|
+
|
|
216869
|
+
You can add a description to the \`${CONTENT_NAME$2}\` by passing a \`${DESCRIPTION_NAME}\` component as a child, which also benefits sighted users by adding visible context to the dialog.
|
|
216870
|
+
|
|
216871
|
+
Alternatively, you can use your own component as a description by assigning it an \`id\` and passing the same value to the \`aria-describedby\` prop in \`${CONTENT_NAME$2}\`. If the description is confusing or duplicative for sighted users, you can use the \`@radix-ui/react-visually-hidden\` primitive as a wrapper around your description component.
|
|
216872
|
+
|
|
216873
|
+
For more information, see https://radix-ui.com/primitives/docs/components/alert-dialog`;
|
|
216874
|
+
React.useEffect(() => {
|
|
216875
|
+
const hasDescription = document.getElementById(
|
|
216876
|
+
contentRef.current?.getAttribute("aria-describedby")
|
|
216877
|
+
);
|
|
216878
|
+
if (!hasDescription) console.warn(MESSAGE);
|
|
216879
|
+
}, [MESSAGE, contentRef]);
|
|
216880
|
+
return null;
|
|
216881
|
+
};
|
|
216882
|
+
var Root2$2 = AlertDialog$1;
|
|
216883
|
+
var Portal2 = AlertDialogPortal$1;
|
|
216884
|
+
var Overlay2 = AlertDialogOverlay$1;
|
|
216885
|
+
var Content2$1 = AlertDialogContent$1;
|
|
216886
|
+
var Action = AlertDialogAction$1;
|
|
216887
|
+
var Cancel = AlertDialogCancel$1;
|
|
216888
|
+
var Title2 = AlertDialogTitle$1;
|
|
216889
|
+
var Description2 = AlertDialogDescription$1;
|
|
216890
|
+
|
|
216891
|
+
const AlertDialog = Root2$2;
|
|
216892
|
+
const AlertDialogPortal = Portal2;
|
|
216893
|
+
const AlertDialogOverlay = React.forwardRef(({ className, ...props }, ref) => (jsx(Overlay2, { className: cn('data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80', className), ...props, ref: ref })));
|
|
216894
|
+
AlertDialogOverlay.displayName = Overlay2.displayName;
|
|
216895
|
+
const AlertDialogContent = React.forwardRef(({ className, ...props }, ref) => (jsxs(AlertDialogPortal, { children: [jsx(AlertDialogOverlay, {}), jsx(Content2$1, { ref: ref, className: cn('bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg', className), ...props })] })));
|
|
216896
|
+
AlertDialogContent.displayName = Content2$1.displayName;
|
|
216897
|
+
const AlertDialogHeader = ({ className, ...props }) => (jsx("div", { className: cn('flex flex-col space-y-2 text-center sm:text-left', className), ...props }));
|
|
216898
|
+
AlertDialogHeader.displayName = 'AlertDialogHeader';
|
|
216899
|
+
const AlertDialogFooter = ({ className, ...props }) => (jsx("div", { className: cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className), ...props }));
|
|
216900
|
+
AlertDialogFooter.displayName = 'AlertDialogFooter';
|
|
216901
|
+
const AlertDialogTitle = React.forwardRef(({ className, ...props }, ref) => (jsx(Title2, { ref: ref, className: cn('text-lg font-semibold', className), ...props })));
|
|
216902
|
+
AlertDialogTitle.displayName = Title2.displayName;
|
|
216903
|
+
const AlertDialogDescription = React.forwardRef(({ className, ...props }, ref) => (jsx(Description2, { ref: ref, className: cn('text-muted-foreground text-sm', className), ...props })));
|
|
216904
|
+
AlertDialogDescription.displayName = Description2.displayName;
|
|
216905
|
+
const AlertDialogAction = React.forwardRef(({ className, ...props }, ref) => (jsx(Action, { ref: ref, className: cn(buttonVariants(), className), ...props })));
|
|
216906
|
+
AlertDialogAction.displayName = Action.displayName;
|
|
216907
|
+
const AlertDialogCancel = React.forwardRef(({ className, ...props }, ref) => (jsx(Cancel, { ref: ref, className: cn(buttonVariants({ variant: 'outline' }), 'mt-2 sm:mt-0', className), ...props })));
|
|
216908
|
+
AlertDialogCancel.displayName = Cancel.displayName;
|
|
216909
|
+
|
|
217186
216910
|
const THEMES = { light: '', dark: '.dark' };
|
|
217187
216911
|
const ChartContext = React.createContext(null);
|
|
217188
216912
|
function useChart() {
|
|
@@ -252992,6 +252716,543 @@ function getLLMProviderDetails(llmProvider, llmName) {
|
|
|
252992
252716
|
}
|
|
252993
252717
|
}
|
|
252994
252718
|
|
|
252719
|
+
function OverlayModal({ open, onClose, title, description, className, children, }) {
|
|
252720
|
+
const t = useT();
|
|
252721
|
+
const [mounted, setMounted] = useState(false);
|
|
252722
|
+
const [dialogPanel, setDialogPanel] = useState(null);
|
|
252723
|
+
useEffect(() => {
|
|
252724
|
+
setMounted(true);
|
|
252725
|
+
}, []);
|
|
252726
|
+
const handleOpenChange = (nextOpen) => {
|
|
252727
|
+
if (!nextOpen)
|
|
252728
|
+
onClose();
|
|
252729
|
+
};
|
|
252730
|
+
if (!mounted || typeof document === 'undefined') {
|
|
252731
|
+
return null;
|
|
252732
|
+
}
|
|
252733
|
+
// Nested Radix Dialog on document.body: viewport-fixed overlay + its own scroll lock,
|
|
252734
|
+
// independent of any parent modal. Requires the app to resolve the same
|
|
252735
|
+
// `@radix-ui/react-dialog` instance as this package (peer dependency + Rollup external).
|
|
252736
|
+
return (jsx(DialogPrimitive.Root, { open: open, onOpenChange: handleOpenChange, modal: true, children: jsxs(DialogPrimitive.Portal, { container: document.body, children: [jsx(DialogPrimitive.Overlay, { "data-iblai-dialog-interaction-layer": true, className: cn('pointer-events-auto fixed inset-0 z-[100] bg-black/60', 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0') }), jsx(DialogPrimitive.Content, { ref: setDialogPanel, "data-iblai-dialog-interaction-layer": true, ...(!description ? { 'aria-describedby': undefined } : {}), className: cn('pointer-events-auto fixed left-[50%] top-[50%] z-[100] grid w-full translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background shadow-lg duration-200', 'max-h-[min(90dvh,calc(100dvh-2rem))] max-w-[calc(100vw-2rem)] overflow-y-auto overscroll-contain rounded-lg p-6 sm:rounded-lg', 'pt-[max(1.5rem,env(safe-area-inset-top))] pb-[max(1.5rem,env(safe-area-inset-bottom))]', 'pl-[max(1.5rem,env(safe-area-inset-left))] pr-[max(1.5rem,env(safe-area-inset-right))]', 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]', 'focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2', className), children: jsxs(FloatingPortalContainerContext.Provider, { value: dialogPanel, children: [jsx(DialogPrimitive.Close, { type: "button", className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", "aria-label": t('clawSandboxOverlayModal.close'), children: jsx(X$2, { className: "h-4 w-4" }) }), jsxs("div", { className: "space-y-4", children: [jsxs("div", { className: "flex flex-col space-y-1.5 pr-8 text-center sm:text-left", children: [jsx(DialogPrimitive.Title, { className: "text-lg font-semibold leading-none tracking-tight", children: title }), description ? (jsx(DialogPrimitive.Description, { className: "text-sm text-muted-foreground", children: description })) : null] }), children] })] }) })] }) }));
|
|
252737
|
+
}
|
|
252738
|
+
|
|
252739
|
+
/** Page size for the resources list inside the Edit Skill dialog. */
|
|
252740
|
+
const RESOURCES_PAGE_SIZE = 20;
|
|
252741
|
+
const EMPTY_RESOURCE_FORM = {
|
|
252742
|
+
file_type: 'reference',
|
|
252743
|
+
filename: '',
|
|
252744
|
+
content: '',
|
|
252745
|
+
};
|
|
252746
|
+
/**
|
|
252747
|
+
* File attachments for a skill (agent-skill-resources). `reference`/`script`
|
|
252748
|
+
* files are text (filename + content); `asset` files are binary uploads.
|
|
252749
|
+
* Rendered as the Files tab of the Edit Skill dialog: a list with row
|
|
252750
|
+
* actions, a New File popup for add/edit, and a delete confirmation.
|
|
252751
|
+
*/
|
|
252752
|
+
function SkillResourcesSection({ platformKey, skillId }) {
|
|
252753
|
+
var _a, _b, _c;
|
|
252754
|
+
const t = useT();
|
|
252755
|
+
const [page, setPage] = useState(1);
|
|
252756
|
+
const { data: resourcePage, isLoading } = useGetAgentSkillResourcesQuery({
|
|
252757
|
+
org: platformKey,
|
|
252758
|
+
skill: skillId,
|
|
252759
|
+
limit: RESOURCES_PAGE_SIZE,
|
|
252760
|
+
offset: (page - 1) * RESOURCES_PAGE_SIZE,
|
|
252761
|
+
});
|
|
252762
|
+
const resources = (_a = resourcePage === null || resourcePage === void 0 ? void 0 : resourcePage.results) !== null && _a !== void 0 ? _a : [];
|
|
252763
|
+
const totalCount = (_b = resourcePage === null || resourcePage === void 0 ? void 0 : resourcePage.count) !== null && _b !== void 0 ? _b : 0;
|
|
252764
|
+
const totalPages = Math.max(1, Math.ceil(totalCount / RESOURCES_PAGE_SIZE));
|
|
252765
|
+
// Deleting the last item of the last page leaves the page out of range —
|
|
252766
|
+
// snap back to the new last page.
|
|
252767
|
+
useEffect(() => {
|
|
252768
|
+
if (page > totalPages)
|
|
252769
|
+
setPage(totalPages);
|
|
252770
|
+
}, [page, totalPages]);
|
|
252771
|
+
const [createResource, { isLoading: isCreating }] = useCreateAgentSkillResourceMutation();
|
|
252772
|
+
const [updateResource, { isLoading: isUpdating }] = useUpdateAgentSkillResourceMutation();
|
|
252773
|
+
const [uploadAsset, { isLoading: isUploading }] = useUploadAgentSkillResourceAssetMutation();
|
|
252774
|
+
const [deleteResource, { isLoading: isDeleting }] = useDeleteAgentSkillResourceMutation();
|
|
252775
|
+
const [showFileDialog, setShowFileDialog] = useState(false);
|
|
252776
|
+
const [editingResource, setEditingResource] = useState(null);
|
|
252777
|
+
const [deletingResource, setDeletingResource] = useState(null);
|
|
252778
|
+
const [form, setForm] = useState(EMPTY_RESOURCE_FORM);
|
|
252779
|
+
const [assetFile, setAssetFile] = useState(null);
|
|
252780
|
+
const fileInputRef = useRef(null);
|
|
252781
|
+
const isSaving = isCreating || isUpdating || isUploading;
|
|
252782
|
+
const isAssetForm = form.file_type === 'asset' && !editingResource;
|
|
252783
|
+
const canSubmitFile = isAssetForm ? !!assetFile : !!form.filename && !!form.content;
|
|
252784
|
+
const typeLabel = (fileType) => {
|
|
252785
|
+
switch (fileType) {
|
|
252786
|
+
case 'script':
|
|
252787
|
+
return t('clawSandboxAgentSkills.fileTypeScript');
|
|
252788
|
+
case 'asset':
|
|
252789
|
+
return t('clawSandboxAgentSkills.fileTypeAsset');
|
|
252790
|
+
default:
|
|
252791
|
+
return t('clawSandboxAgentSkills.fileTypeReference');
|
|
252792
|
+
}
|
|
252793
|
+
};
|
|
252794
|
+
const openNewFileDialog = () => {
|
|
252795
|
+
setForm(EMPTY_RESOURCE_FORM);
|
|
252796
|
+
setAssetFile(null);
|
|
252797
|
+
setEditingResource(null);
|
|
252798
|
+
setShowFileDialog(true);
|
|
252799
|
+
};
|
|
252800
|
+
const openEditFileDialog = (resource) => {
|
|
252801
|
+
var _a, _b;
|
|
252802
|
+
setForm({
|
|
252803
|
+
file_type: (_a = resource.file_type) !== null && _a !== void 0 ? _a : 'reference',
|
|
252804
|
+
filename: resource.filename,
|
|
252805
|
+
content: (_b = resource.content) !== null && _b !== void 0 ? _b : '',
|
|
252806
|
+
});
|
|
252807
|
+
setAssetFile(null);
|
|
252808
|
+
setEditingResource(resource);
|
|
252809
|
+
setShowFileDialog(true);
|
|
252810
|
+
};
|
|
252811
|
+
const closeFileDialog = () => {
|
|
252812
|
+
setShowFileDialog(false);
|
|
252813
|
+
setEditingResource(null);
|
|
252814
|
+
setForm(EMPTY_RESOURCE_FORM);
|
|
252815
|
+
setAssetFile(null);
|
|
252816
|
+
};
|
|
252817
|
+
const handleSubmitFile = async () => {
|
|
252818
|
+
try {
|
|
252819
|
+
if (editingResource) {
|
|
252820
|
+
await updateResource({
|
|
252821
|
+
org: platformKey,
|
|
252822
|
+
id: editingResource.id,
|
|
252823
|
+
filename: form.filename,
|
|
252824
|
+
content: form.content,
|
|
252825
|
+
}).unwrap();
|
|
252826
|
+
toast.success(t('clawSandboxAgentSkills.fileSaved'));
|
|
252827
|
+
}
|
|
252828
|
+
else if (isAssetForm) {
|
|
252829
|
+
if (!assetFile)
|
|
252830
|
+
return;
|
|
252831
|
+
await uploadAsset({
|
|
252832
|
+
org: platformKey,
|
|
252833
|
+
skill: skillId,
|
|
252834
|
+
file: assetFile,
|
|
252835
|
+
filename: assetFile.name,
|
|
252836
|
+
}).unwrap();
|
|
252837
|
+
toast.success(t('clawSandboxAgentSkills.fileUploaded'));
|
|
252838
|
+
}
|
|
252839
|
+
else {
|
|
252840
|
+
await createResource({
|
|
252841
|
+
org: platformKey,
|
|
252842
|
+
skill: skillId,
|
|
252843
|
+
file_type: form.file_type,
|
|
252844
|
+
filename: form.filename,
|
|
252845
|
+
content: form.content,
|
|
252846
|
+
}).unwrap();
|
|
252847
|
+
toast.success(t('clawSandboxAgentSkills.fileAdded'));
|
|
252848
|
+
}
|
|
252849
|
+
closeFileDialog();
|
|
252850
|
+
}
|
|
252851
|
+
catch (_a) {
|
|
252852
|
+
toast.error(t(isAssetForm
|
|
252853
|
+
? 'clawSandboxAgentSkills.failedToUploadFile'
|
|
252854
|
+
: 'clawSandboxAgentSkills.failedToSaveFile'));
|
|
252855
|
+
}
|
|
252856
|
+
};
|
|
252857
|
+
const handleDeleteFile = async () => {
|
|
252858
|
+
if (!deletingResource)
|
|
252859
|
+
return;
|
|
252860
|
+
try {
|
|
252861
|
+
await deleteResource({ org: platformKey, id: deletingResource.id }).unwrap();
|
|
252862
|
+
toast.success(t('clawSandboxAgentSkills.fileDeleted'));
|
|
252863
|
+
setDeletingResource(null);
|
|
252864
|
+
}
|
|
252865
|
+
catch (_a) {
|
|
252866
|
+
toast.error(t('clawSandboxAgentSkills.failedToDeleteFile'));
|
|
252867
|
+
}
|
|
252868
|
+
};
|
|
252869
|
+
const submitLabel = () => {
|
|
252870
|
+
if (editingResource) {
|
|
252871
|
+
return isUpdating ? t('clawSandboxAgentSkills.saving') : t('clawSandboxAgentSkills.save');
|
|
252872
|
+
}
|
|
252873
|
+
if (isAssetForm) {
|
|
252874
|
+
return isUploading
|
|
252875
|
+
? t('clawSandboxAgentSkills.uploading')
|
|
252876
|
+
: t('clawSandboxAgentSkills.upload');
|
|
252877
|
+
}
|
|
252878
|
+
return isCreating ? t('clawSandboxAgentSkills.adding') : t('clawSandboxAgentSkills.addFileButton');
|
|
252879
|
+
};
|
|
252880
|
+
return (jsxs("div", { className: "space-y-4", "data-testid": "skill-resources-section", children: [jsxs("div", { className: "flex items-start justify-between gap-4", children: [jsx("p", { className: "text-xs text-gray-500", children: t('clawSandboxAgentSkills.filesHint') }), jsxs(Button$1, { onClick: openNewFileDialog, size: "sm", className: "shrink-0 cursor-pointer bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: [jsx(Plus, { className: "h-4 w-4" }), t('clawSandboxAgentSkills.newFile')] })] }), isLoading ? (jsxs("div", { className: "flex items-center gap-2 p-4", role: "status", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin text-blue-500" }), jsx("span", { className: "text-sm text-gray-500", children: t('clawSandboxAgentSkills.loadingFiles') })] })) : resources.length === 0 ? (jsx("div", { className: "flex items-center justify-center rounded-lg border p-6", children: jsx("p", { className: "text-sm text-gray-500", children: t('clawSandboxAgentSkills.noFiles') }) })) : (jsxs("div", { className: "space-y-3", children: [resources.map((resource) => (jsxs("div", { className: "flex items-center justify-between gap-4 rounded-lg border p-4", children: [jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [jsx(Paperclip, { className: "h-4 w-4 shrink-0 text-gray-400" }), jsx("span", { className: "truncate text-sm font-medium text-gray-700", children: resource.filename }), jsx("span", { className: "rounded-full bg-gray-100 px-2 py-0.5 text-[0.625rem] text-gray-500", children: typeLabel(resource.file_type) })] }), jsx(FloatingPortalContainerContext.Provider, { value: null, children: jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsx(Button$1, { variant: "ghost", size: "sm", "aria-label": t('clawSandboxAgentSkills.skillActions', {
|
|
252881
|
+
name: resource.filename,
|
|
252882
|
+
}), children: jsx(Ellipsis, { className: "h-4 w-4" }) }) }), jsxs(DropdownMenuContent, { align: "end", className: "z-[110]", children: [resource.file_type === 'asset' && resource.file && (jsx(DropdownMenuItem, { asChild: true, className: "cursor-pointer", children: jsxs("a", { href: resource.file, target: "_blank", rel: "noreferrer", download: true, children: [jsx(Download, { className: "mr-2 h-4 w-4" }), t('clawSandboxAgentSkills.download')] }) })), resource.file_type !== 'asset' && (jsxs(DropdownMenuItem, { className: "cursor-pointer", onClick: () => openEditFileDialog(resource), children: [jsx(Pen, { className: "mr-2 h-4 w-4" }), t('clawSandboxAgentSkills.edit')] })), jsxs(DropdownMenuItem, { variant: "destructive", className: "cursor-pointer", onClick: () => setDeletingResource(resource), children: [jsx(Trash2, { className: "mr-2 h-4 w-4" }), t('clawSandboxAgentSkills.delete')] })] })] }) })] }, resource.id))), jsx(AdvancedPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, totalCount: totalCount, itemsPerPage: RESOURCES_PAGE_SIZE, itemLabel: t('clawSandboxAgentSkills.resourcesItemLabel') })] })), jsxs(OverlayModal, { open: showFileDialog, onClose: closeFileDialog, title: t(editingResource
|
|
252883
|
+
? 'clawSandboxAgentSkills.editFileDialogTitle'
|
|
252884
|
+
: 'clawSandboxAgentSkills.newFileDialogTitle'), className: "max-w-lg", children: [jsxs("div", { className: "mt-4 grid gap-4", children: [!editingResource && (jsxs("div", { className: "space-y-2", children: [jsx(Label$1, { htmlFor: "resource-type", className: "text-sm font-medium text-[#646464]", children: t('clawSandboxAgentSkills.fileTypeLabel') }), jsxs(Select$1, { value: form.file_type, onValueChange: (value) => setForm({ ...form, file_type: value }), children: [jsx(SelectTrigger, { id: "resource-type", className: "w-full", children: jsx(SelectValue, {}) }), jsxs(SelectContent, { children: [jsx(SelectItem, { value: "reference", children: t('clawSandboxAgentSkills.fileTypeReference') }), jsx(SelectItem, { value: "script", children: t('clawSandboxAgentSkills.fileTypeScript') }), jsx(SelectItem, { value: "asset", children: t('clawSandboxAgentSkills.fileTypeAsset') })] })] })] })), isAssetForm ? (jsxs("div", { className: "space-y-2", children: [jsx(Label$1, { htmlFor: "resource-file", className: "text-sm font-medium text-[#646464]", children: t('clawSandboxAgentSkills.fileNameLabel') }), jsx("input", { ref: fileInputRef, id: "resource-file", type: "file", className: "hidden", onChange: (e) => { var _a, _b; return setAssetFile((_b = (_a = e.target.files) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : null); }, "data-testid": "resource-file-input" }), jsxs("div", { className: "flex items-center gap-2", children: [jsxs(Button$1, { variant: "outline", size: "sm", onClick: () => { var _a; return (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, children: [jsx(Paperclip, { className: "h-4 w-4" }), t('clawSandboxAgentSkills.chooseFile')] }), assetFile && (jsx("span", { className: "truncate text-sm text-gray-600", children: assetFile.name }))] })] })) : (jsxs(Fragment$1, { children: [jsxs("div", { className: "space-y-2", children: [jsx(Label$1, { htmlFor: "resource-filename", className: "text-sm font-medium text-[#646464]", children: t('clawSandboxAgentSkills.fileNameLabel') }), jsx(Input, { id: "resource-filename", name: "resource-filename", value: form.filename, onChange: (e) => setForm({ ...form, filename: e.target.value }), placeholder: t('clawSandboxAgentSkills.fileNamePlaceholder'), className: "py-6" })] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$1, { htmlFor: "resource-content", className: "text-sm font-medium text-[#646464]", children: t('clawSandboxAgentSkills.fileContentLabel') }), jsx(Textarea, { id: "resource-content", name: "resource-content", value: form.content, onChange: (e) => setForm({ ...form, content: e.target.value }), placeholder: t('clawSandboxAgentSkills.fileContentPlaceholder'), rows: 6 })] })] }))] }), jsxs("div", { className: "flex justify-end gap-2 pt-2", children: [jsx(Button$1, { variant: "outline", onClick: closeFileDialog, children: t('clawSandboxAgentSkills.cancel') }), jsx(Button$1, { onClick: handleSubmitFile, disabled: isSaving || !canSubmitFile, className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: submitLabel() })] })] }), jsxs(OverlayModal, { open: !!deletingResource, onClose: () => setDeletingResource(null), title: t('clawSandboxAgentSkills.deleteFileDialogTitle'), className: "max-w-md", children: [jsx("p", { className: "mt-2 text-sm text-gray-600", children: t('clawSandboxAgentSkills.deleteFileConfirmation', {
|
|
252885
|
+
name: (_c = deletingResource === null || deletingResource === void 0 ? void 0 : deletingResource.filename) !== null && _c !== void 0 ? _c : '',
|
|
252886
|
+
}) }), jsxs("div", { className: "flex justify-end gap-2 pt-2", children: [jsx(Button$1, { variant: "outline", onClick: () => setDeletingResource(null), children: t('clawSandboxAgentSkills.cancel') }), jsx(Button$1, { onClick: handleDeleteFile, disabled: isDeleting, className: "bg-red-600 text-white hover:bg-red-700", children: isDeleting
|
|
252887
|
+
? t('clawSandboxAgentSkills.deleting')
|
|
252888
|
+
: t('clawSandboxAgentSkills.delete') })] })] })] }));
|
|
252889
|
+
}
|
|
252890
|
+
|
|
252891
|
+
const EMPTY_SKILL_FORM = {
|
|
252892
|
+
name: '',
|
|
252893
|
+
slug: '',
|
|
252894
|
+
description: '',
|
|
252895
|
+
version: '1.0.0',
|
|
252896
|
+
category: '',
|
|
252897
|
+
instruction: '',
|
|
252898
|
+
privateToAgent: false,
|
|
252899
|
+
};
|
|
252900
|
+
// The builder resolves the effective skill set client-side, which needs the
|
|
252901
|
+
// complete catalog and assignment lists. Request one explicit large page so
|
|
252902
|
+
// the result is deterministic even if the backend later configures a default
|
|
252903
|
+
// page size (the list endpoints unwrap paginated envelopes to `results`).
|
|
252904
|
+
const FULL_LIST_LIMIT = 1000;
|
|
252905
|
+
function AgentSkills({ platformKey, mentorUniqueId }) {
|
|
252906
|
+
var _a;
|
|
252907
|
+
const t = useT();
|
|
252908
|
+
// Skills are managed independently of the sandbox connection — org-level
|
|
252909
|
+
// skills and the mentor's assignments both resolve without a wired Claw
|
|
252910
|
+
// instance, so we always fetch and let admins add/assign skills freely.
|
|
252911
|
+
// Always fetch — the backend enforces read access; RBAC here only gates
|
|
252912
|
+
// the write affordances (a partial permissions map must not blank the UI).
|
|
252913
|
+
const { data: availableSkills, isLoading: isLoadingSkills } = useGetAgentSkillsQuery({
|
|
252914
|
+
org: platformKey,
|
|
252915
|
+
limit: FULL_LIST_LIMIT,
|
|
252916
|
+
offset: 0,
|
|
252917
|
+
});
|
|
252918
|
+
const { data: assignments, isLoading: isLoadingAssignments } = useGetMentorSkillAssignmentsQuery({
|
|
252919
|
+
org: platformKey,
|
|
252920
|
+
mentorUniqueId,
|
|
252921
|
+
limit: FULL_LIST_LIMIT,
|
|
252922
|
+
offset: 0,
|
|
252923
|
+
});
|
|
252924
|
+
// Assignment mutations (attach/detach/toggle on the agent)
|
|
252925
|
+
const [createAssignment, { isLoading: isCreatingAssignment }] = useCreateMentorSkillAssignmentMutation();
|
|
252926
|
+
const [updateAssignment, { isLoading: isUpdatingAssignment }] = useUpdateMentorSkillAssignmentMutation();
|
|
252927
|
+
const [deleteAssignment, { isLoading: isDeletingAssignment }] = useDeleteMentorSkillAssignmentMutation();
|
|
252928
|
+
// Skill CRUD mutations (platform-level)
|
|
252929
|
+
const [createSkill, { isLoading: isCreatingSkill }] = useCreateAgentSkillMutation();
|
|
252930
|
+
const [updateSkill, { isLoading: isUpdatingSkill }] = useUpdateAgentSkillMutation();
|
|
252931
|
+
const [deleteSkill, { isLoading: isDeletingSkill }] = useDeleteAgentSkillMutation();
|
|
252932
|
+
const [showNewDialog, setShowNewDialog] = useState(false);
|
|
252933
|
+
const [editingSkill, setEditingSkill] = useState(null);
|
|
252934
|
+
const [deletingSkill, setDeletingSkill] = useState(null);
|
|
252935
|
+
const [form, setForm] = useState(EMPTY_SKILL_FORM);
|
|
252936
|
+
const isLoading = isLoadingSkills || isLoadingAssignments;
|
|
252937
|
+
const isMutatingAgentSkill = isCreatingAssignment || isUpdatingAssignment || isDeletingAssignment || isUpdatingSkill;
|
|
252938
|
+
const allSkills = availableSkills !== null && availableSkills !== void 0 ? availableSkills : [];
|
|
252939
|
+
const effectiveSkills = resolveEffectiveAgentSkills(allSkills, assignments !== null && assignments !== void 0 ? assignments : [], mentorUniqueId);
|
|
252940
|
+
const effectiveUniqueIds = new Set(effectiveSkills.map((s) => s.unique_id));
|
|
252941
|
+
const effectiveSlugs = new Set(effectiveSkills.map((s) => s.slug));
|
|
252942
|
+
// Catalog skills this agent could still attach: enabled, platform-wide
|
|
252943
|
+
// (never another agent's private skills), and not already effective. A
|
|
252944
|
+
// skill whose slug is already effective (e.g. shadowed by a private skill)
|
|
252945
|
+
// would dedupe away after attaching — don't offer an Add that does nothing.
|
|
252946
|
+
const attachableSkills = allSkills.filter((skill) => skill.enabled &&
|
|
252947
|
+
!skill.mentor &&
|
|
252948
|
+
!effectiveUniqueIds.has(skill.unique_id) &&
|
|
252949
|
+
!effectiveSlugs.has(skill.slug));
|
|
252950
|
+
// Featured skills from the `main` platform are read-only for tenants — the
|
|
252951
|
+
// API 404s writes against them, so hide the edit/delete affordances.
|
|
252952
|
+
const isSkillEditable = (skill) => {
|
|
252953
|
+
if (!skill)
|
|
252954
|
+
return false;
|
|
252955
|
+
return skill.platform_key ? skill.platform_key === platformKey : !skill.is_featured;
|
|
252956
|
+
};
|
|
252957
|
+
const resetForm = () => setForm(EMPTY_SKILL_FORM);
|
|
252958
|
+
const handleToggleEffective = async (effective, shouldEnable) => {
|
|
252959
|
+
try {
|
|
252960
|
+
if (effective.origin === 'private' && effective.skill) {
|
|
252961
|
+
await updateSkill({
|
|
252962
|
+
org: platformKey,
|
|
252963
|
+
id: effective.skill.id,
|
|
252964
|
+
enabled: shouldEnable,
|
|
252965
|
+
}).unwrap();
|
|
252966
|
+
}
|
|
252967
|
+
else if (effective.assignmentId !== undefined) {
|
|
252968
|
+
await updateAssignment({
|
|
252969
|
+
org: platformKey,
|
|
252970
|
+
mentorUniqueId,
|
|
252971
|
+
assignmentPk: effective.assignmentId,
|
|
252972
|
+
enabled: shouldEnable,
|
|
252973
|
+
}).unwrap();
|
|
252974
|
+
}
|
|
252975
|
+
toast.success(t(shouldEnable
|
|
252976
|
+
? 'clawSandboxAgentSkills.skillEnabled'
|
|
252977
|
+
: 'clawSandboxAgentSkills.skillDisabled', { name: effective.name }));
|
|
252978
|
+
}
|
|
252979
|
+
catch (_a) {
|
|
252980
|
+
toast.error(t('clawSandboxAgentSkills.failedToUpdateSkill', { name: effective.name }));
|
|
252981
|
+
}
|
|
252982
|
+
};
|
|
252983
|
+
const handleAttach = async (skill) => {
|
|
252984
|
+
try {
|
|
252985
|
+
await createAssignment({
|
|
252986
|
+
org: platformKey,
|
|
252987
|
+
mentorUniqueId,
|
|
252988
|
+
skill: skill.unique_id,
|
|
252989
|
+
enabled: true,
|
|
252990
|
+
}).unwrap();
|
|
252991
|
+
toast.success(t('clawSandboxAgentSkills.skillAdded', { name: skill.name }));
|
|
252992
|
+
}
|
|
252993
|
+
catch (_a) {
|
|
252994
|
+
toast.error(t('clawSandboxAgentSkills.failedToUpdateSkill', { name: skill.name }));
|
|
252995
|
+
}
|
|
252996
|
+
};
|
|
252997
|
+
const handleDetach = async (effective) => {
|
|
252998
|
+
if (effective.assignmentId === undefined)
|
|
252999
|
+
return;
|
|
253000
|
+
try {
|
|
253001
|
+
await deleteAssignment({
|
|
253002
|
+
org: platformKey,
|
|
253003
|
+
mentorUniqueId,
|
|
253004
|
+
assignmentPk: effective.assignmentId,
|
|
253005
|
+
}).unwrap();
|
|
253006
|
+
toast.success(t('clawSandboxAgentSkills.skillRemoved', { name: effective.name }));
|
|
253007
|
+
}
|
|
253008
|
+
catch (_a) {
|
|
253009
|
+
toast.error(t('clawSandboxAgentSkills.failedToUpdateSkill', { name: effective.name }));
|
|
253010
|
+
}
|
|
253011
|
+
};
|
|
253012
|
+
const openNewSkillDialog = () => {
|
|
253013
|
+
resetForm();
|
|
253014
|
+
setShowNewDialog(true);
|
|
253015
|
+
};
|
|
253016
|
+
const openEditSkillDialog = (skill) => {
|
|
253017
|
+
var _a;
|
|
253018
|
+
setForm({
|
|
253019
|
+
name: skill.name,
|
|
253020
|
+
slug: skill.slug,
|
|
253021
|
+
description: skill.description,
|
|
253022
|
+
version: skill.version,
|
|
253023
|
+
category: (_a = skill.category) !== null && _a !== void 0 ? _a : '',
|
|
253024
|
+
instruction: skill.instruction,
|
|
253025
|
+
privateToAgent: skill.mentor === mentorUniqueId,
|
|
253026
|
+
});
|
|
253027
|
+
setEditingSkill(skill);
|
|
253028
|
+
};
|
|
253029
|
+
const closeAllDialogs = () => {
|
|
253030
|
+
setShowNewDialog(false);
|
|
253031
|
+
setEditingSkill(null);
|
|
253032
|
+
resetForm();
|
|
253033
|
+
};
|
|
253034
|
+
const handleCreateSkill = async () => {
|
|
253035
|
+
if (!form.name || !form.slug) {
|
|
253036
|
+
toast.error(t('clawSandboxAgentSkills.nameAndSlugRequired'));
|
|
253037
|
+
return;
|
|
253038
|
+
}
|
|
253039
|
+
try {
|
|
253040
|
+
await createSkill({
|
|
253041
|
+
org: platformKey,
|
|
253042
|
+
name: form.name,
|
|
253043
|
+
slug: form.slug,
|
|
253044
|
+
description: form.description,
|
|
253045
|
+
version: form.version || '1.0.0',
|
|
253046
|
+
...(form.category && { category: form.category }),
|
|
253047
|
+
...(form.privateToAgent && { mentor: mentorUniqueId }),
|
|
253048
|
+
instruction: form.instruction,
|
|
253049
|
+
enabled: true,
|
|
253050
|
+
}).unwrap();
|
|
253051
|
+
toast.success(t('clawSandboxAgentSkills.skillCreated'));
|
|
253052
|
+
closeAllDialogs();
|
|
253053
|
+
}
|
|
253054
|
+
catch (_a) {
|
|
253055
|
+
toast.error(t('clawSandboxAgentSkills.failedToCreateSkill'));
|
|
253056
|
+
}
|
|
253057
|
+
};
|
|
253058
|
+
const handleUpdateSkill = async () => {
|
|
253059
|
+
if (!editingSkill)
|
|
253060
|
+
return;
|
|
253061
|
+
if (!form.name || !form.slug) {
|
|
253062
|
+
toast.error(t('clawSandboxAgentSkills.nameAndSlugRequired'));
|
|
253063
|
+
return;
|
|
253064
|
+
}
|
|
253065
|
+
try {
|
|
253066
|
+
await updateSkill({
|
|
253067
|
+
org: platformKey,
|
|
253068
|
+
id: editingSkill.id,
|
|
253069
|
+
name: form.name,
|
|
253070
|
+
slug: form.slug,
|
|
253071
|
+
description: form.description,
|
|
253072
|
+
version: form.version,
|
|
253073
|
+
category: form.category,
|
|
253074
|
+
instruction: form.instruction,
|
|
253075
|
+
}).unwrap();
|
|
253076
|
+
toast.success(t('clawSandboxAgentSkills.skillUpdated'));
|
|
253077
|
+
closeAllDialogs();
|
|
253078
|
+
}
|
|
253079
|
+
catch (_a) {
|
|
253080
|
+
toast.error(t('clawSandboxAgentSkills.failedToUpdateSkillGeneric'));
|
|
253081
|
+
}
|
|
253082
|
+
};
|
|
253083
|
+
const handleDeleteSkill = async () => {
|
|
253084
|
+
if (!deletingSkill)
|
|
253085
|
+
return;
|
|
253086
|
+
try {
|
|
253087
|
+
await deleteSkill({ org: platformKey, id: deletingSkill.id }).unwrap();
|
|
253088
|
+
toast.success(t('clawSandboxAgentSkills.skillDeleted'));
|
|
253089
|
+
setDeletingSkill(null);
|
|
253090
|
+
}
|
|
253091
|
+
catch (_a) {
|
|
253092
|
+
toast.error(t('clawSandboxAgentSkills.failedToDeleteSkill'));
|
|
253093
|
+
}
|
|
253094
|
+
};
|
|
253095
|
+
const renderBadges = (skill, effective) => {
|
|
253096
|
+
var _a, _b, _c;
|
|
253097
|
+
const category = (_a = effective === null || effective === void 0 ? void 0 : effective.category) !== null && _a !== void 0 ? _a : skill === null || skill === void 0 ? void 0 : skill.category;
|
|
253098
|
+
const skillType = (_b = effective === null || effective === void 0 ? void 0 : effective.skill_type) !== null && _b !== void 0 ? _b : skill === null || skill === void 0 ? void 0 : skill.skill_type;
|
|
253099
|
+
const isFeatured = (_c = effective === null || effective === void 0 ? void 0 : effective.is_featured) !== null && _c !== void 0 ? _c : skill === null || skill === void 0 ? void 0 : skill.is_featured;
|
|
253100
|
+
return (jsxs("span", { className: "flex flex-wrap items-center gap-1", children: [category && (jsx("span", { className: "rounded-full bg-gray-100 px-2 py-0.5 text-[0.625rem] text-gray-500", children: category })), skillType === 'native' && (jsx("span", { className: "rounded-full bg-purple-50 px-2 py-0.5 text-[0.625rem] text-purple-600", children: t('clawSandboxAgentSkills.nativeBadge') })), isFeatured && (jsx("span", { className: "rounded-full bg-amber-50 px-2 py-0.5 text-[0.625rem] text-amber-600", children: t('clawSandboxAgentSkills.featuredBadge') })), (effective === null || effective === void 0 ? void 0 : effective.origin) === 'private' && (jsx("span", { className: "rounded-full bg-blue-50 px-2 py-0.5 text-[0.625rem] text-blue-600", children: t('clawSandboxAgentSkills.privateBadge') }))] }));
|
|
253101
|
+
};
|
|
253102
|
+
const renderSkillMenu = (skill, effective) => {
|
|
253103
|
+
var _a, _b;
|
|
253104
|
+
const editable = isSkillEditable(skill);
|
|
253105
|
+
const showEdit = editable;
|
|
253106
|
+
const showDelete = editable;
|
|
253107
|
+
const detachable = (effective === null || effective === void 0 ? void 0 : effective.origin) === 'assignment';
|
|
253108
|
+
if (!showEdit && !showDelete && !detachable)
|
|
253109
|
+
return null;
|
|
253110
|
+
const name = (_b = (_a = effective === null || effective === void 0 ? void 0 : effective.name) !== null && _a !== void 0 ? _a : skill === null || skill === void 0 ? void 0 : skill.name) !== null && _b !== void 0 ? _b : '';
|
|
253111
|
+
return (jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsx(Button$1, { variant: "ghost", size: "sm", "aria-label": t('clawSandboxAgentSkills.skillActions', { name }), children: jsx(Ellipsis, { className: "h-4 w-4" }) }) }), jsxs(DropdownMenuContent, { align: "end", children: [detachable && (jsxs(DropdownMenuItem, { className: "cursor-pointer", onClick: () => effective && handleDetach(effective), children: [jsx(CircleMinus$1, { className: "mr-2 h-4 w-4" }), t('clawSandboxAgentSkills.removeFromAgent')] })), showEdit && skill && (jsxs(DropdownMenuItem, { className: "cursor-pointer", onClick: () => openEditSkillDialog(skill), children: [jsx(Pen, { className: "mr-2 h-4 w-4" }), t('clawSandboxAgentSkills.edit')] })), showDelete && skill && (jsxs(DropdownMenuItem, { variant: "destructive", className: "cursor-pointer", onClick: () => setDeletingSkill(skill), children: [jsx(Trash2, { className: "mr-2 h-4 w-4" }), t('clawSandboxAgentSkills.delete')] }))] })] }));
|
|
253112
|
+
};
|
|
253113
|
+
if (isLoading) {
|
|
253114
|
+
return (jsxs("div", { className: "flex items-center gap-2 p-4", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin text-blue-500" }), jsx("span", { className: "text-sm text-gray-500", children: t('clawSandboxAgentSkills.loadingSkills') })] }));
|
|
253115
|
+
}
|
|
253116
|
+
return (jsxs("div", { className: "space-y-4", "data-testid": "agent-skills-content", children: [jsxs("div", { className: "flex items-start justify-between gap-4", children: [jsxs("p", { className: "flex items-start gap-2 text-xs text-gray-500", children: [jsx(Info$3, { className: "mt-0.5 h-4 w-4 shrink-0 text-gray-400" }), jsx("span", { children: t('clawSandboxAgentSkills.sessionNote') })] }), jsxs(Button$1, { onClick: openNewSkillDialog, size: "sm", className: "shrink-0 cursor-pointer bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: [jsx(Plus, { className: "h-4 w-4" }), t('clawSandboxAgentSkills.newSkill')] })] }), jsxs("div", { className: "space-y-2", children: [jsx("h3", { className: "text-sm font-semibold text-gray-700", children: t('clawSandboxAgentSkills.effectiveHeading') }), effectiveSkills.length === 0 ? (jsx("div", { className: "flex items-center justify-center rounded-lg border p-6", children: jsx("p", { className: "text-sm text-gray-500", children: t('clawSandboxAgentSkills.noEffectiveSkills') }) })) : (jsx("div", { className: "space-y-3", children: effectiveSkills.map((effective) => {
|
|
253117
|
+
var _a;
|
|
253118
|
+
return (jsxs("div", { className: "flex items-center justify-between gap-4 rounded-lg border p-4", children: [jsxs("div", { className: "min-w-0 space-y-1", children: [jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [jsx("span", { className: "text-sm font-medium text-gray-700", children: effective.name }), ((_a = effective.skill) === null || _a === void 0 ? void 0 : _a.version) && (jsxs("span", { className: "hidden text-xs text-gray-400 sm:inline", children: ["v", effective.skill.version] })), renderBadges(effective.skill, effective)] }), effective.description && (jsx("p", { className: "line-clamp-2 text-xs text-gray-500", children: effective.description }))] }), jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [jsx(Switch, { checked: effective.enabled, onCheckedChange: (checked) => handleToggleEffective(effective, checked), disabled: isMutatingAgentSkill, className: "cursor-pointer data-[state=checked]:bg-blue-500", "aria-label": t(effective.enabled
|
|
253119
|
+
? 'clawSandboxAgentSkills.skillEnabledLabel'
|
|
253120
|
+
: 'clawSandboxAgentSkills.skillDisabledLabel', { name: effective.name }) }), renderSkillMenu(effective.skill, effective)] })] }, effective.unique_id));
|
|
253121
|
+
}) }))] }), jsxs("div", { className: "space-y-2", children: [jsx("h3", { className: "text-sm font-semibold text-gray-700", children: t('clawSandboxAgentSkills.catalogHeading') }), attachableSkills.length === 0 ? (jsx("div", { className: "flex items-center justify-center rounded-lg border p-6", children: jsx("p", { className: "text-sm text-gray-500", children: t('clawSandboxAgentSkills.noSkillsAvailable') }) })) : (jsx("div", { className: "space-y-3", children: attachableSkills.map((skill) => (jsxs("div", { className: "flex items-center justify-between gap-4 rounded-lg border p-4", children: [jsxs("div", { className: "min-w-0 space-y-1", children: [jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [jsx("span", { className: "text-sm font-medium text-gray-700", children: skill.name }), jsxs("span", { className: "hidden text-xs text-gray-400 sm:inline", children: ["v", skill.version] }), renderBadges(skill)] }), skill.description && (jsx("p", { className: "line-clamp-2 text-xs text-gray-500", children: skill.description }))] }), jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [jsxs(Button$1, { variant: "outline", size: "sm", className: "cursor-pointer", disabled: isMutatingAgentSkill, onClick: () => handleAttach(skill), "aria-label": t('clawSandboxAgentSkills.addToAgentLabel', { name: skill.name }), children: [jsx(Plus, { className: "h-4 w-4" }), t('clawSandboxAgentSkills.addToAgent')] }), renderSkillMenu(skill)] })] }, skill.id))) }))] }), jsx(OverlayModal, { open: showNewDialog, onClose: closeAllDialogs, title: t('clawSandboxAgentSkills.newSkillDialogTitle'), className: "max-w-2xl", children: jsxs("div", { className: "flex h-[min(75dvh,46rem)] flex-col", children: [jsxs("div", { className: "flex-1 space-y-4 overflow-y-auto pb-4 pr-1", children: [jsx(SkillForm, { form: form, onChange: setForm, showPrivateToggle: true }), jsx("p", { className: "text-xs text-gray-500", children: t('clawSandboxAgentSkills.filesAfterCreateHint') })] }), jsxs("div", { className: "flex justify-end gap-2 border-t pt-4", children: [jsx(Button$1, { variant: "outline", onClick: closeAllDialogs, children: t('clawSandboxAgentSkills.cancel') }), jsx(Button$1, { onClick: handleCreateSkill, disabled: isCreatingSkill || !form.name || !form.slug, className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: isCreatingSkill
|
|
253122
|
+
? t('clawSandboxAgentSkills.creating')
|
|
253123
|
+
: t('clawSandboxAgentSkills.create') })] })] }) }), jsx(OverlayModal, { open: !!editingSkill, onClose: closeAllDialogs, title: t('clawSandboxAgentSkills.editSkillDialogTitle'), className: "max-w-2xl", children: jsxs(Tabs, { defaultValue: "details", className: "w-full", children: [jsxs(TabsList, { "aria-label": t('clawSandboxAgentSkills.editSkillDialogTitle'), "data-testid": "skill-dialog-tabs", children: [jsx(TabsTrigger, { value: "details", "data-testid": "skill-dialog-tab-details", children: t('clawSandboxAgentSkills.detailsTab') }), jsx(TabsTrigger, { value: "files", "data-testid": "skill-dialog-tab-files", children: t('clawSandboxAgentSkills.filesTab') })] }), jsx(TabsContent, { value: "details", children: jsxs("div", { className: "flex h-[min(75dvh,46rem)] flex-col", children: [jsx("div", { className: "flex-1 space-y-4 overflow-y-auto pb-4 pr-1", children: jsx(SkillForm, { form: form, onChange: setForm }) }), jsxs("div", { className: "flex justify-end gap-2 border-t pt-4", children: [jsx(Button$1, { variant: "outline", onClick: closeAllDialogs, children: t('clawSandboxAgentSkills.cancel') }), jsx(Button$1, { onClick: handleUpdateSkill, disabled: isUpdatingSkill || !form.name || !form.slug, className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: isUpdatingSkill
|
|
253124
|
+
? t('clawSandboxAgentSkills.saving')
|
|
253125
|
+
: t('clawSandboxAgentSkills.save') })] })] }) }), jsx(TabsContent, { value: "files", children: jsx("div", { className: "flex h-[min(75dvh,46rem)] flex-col", children: jsx("div", { className: "flex-1 space-y-4 overflow-y-auto pb-4 pr-1", children: editingSkill && (jsx(SkillResourcesSection, { platformKey: platformKey, skillId: editingSkill.id })) }) }) })] }) }), jsxs(OverlayModal, { open: !!deletingSkill, onClose: () => setDeletingSkill(null), title: t('clawSandboxAgentSkills.deleteSkillDialogTitle'), className: "max-w-md", children: [jsx("p", { className: "mt-2 text-sm text-gray-600", children: t('clawSandboxAgentSkills.deleteConfirmation', { name: (_a = deletingSkill === null || deletingSkill === void 0 ? void 0 : deletingSkill.name) !== null && _a !== void 0 ? _a : '' }) }), jsxs("div", { className: "flex justify-end gap-2 pt-2", children: [jsx(Button$1, { variant: "outline", onClick: () => setDeletingSkill(null), children: t('clawSandboxAgentSkills.cancel') }), jsx(Button$1, { onClick: handleDeleteSkill, disabled: isDeletingSkill, className: "bg-red-600 text-white hover:bg-red-700", children: isDeletingSkill
|
|
253126
|
+
? t('clawSandboxAgentSkills.deleting')
|
|
253127
|
+
: t('clawSandboxAgentSkills.delete') })] })] })] }));
|
|
253128
|
+
}
|
|
253129
|
+
// ── Shared Skill Form ────────────────────────────────────────────────────────
|
|
253130
|
+
function SkillForm({ form, onChange, showPrivateToggle = false, }) {
|
|
253131
|
+
const t = useT();
|
|
253132
|
+
return (jsxs("div", { className: "mt-4 grid gap-4", children: [jsxs("div", { className: "space-y-2", children: [jsx(Label$1, { htmlFor: "skill-name", className: "text-sm font-medium text-[#646464]", children: t('clawSandboxAgentSkills.fieldName') }), jsx(Input, { id: "skill-name", name: "skill-name", value: form.name, onChange: (e) => onChange({ ...form, name: e.target.value }), placeholder: t('clawSandboxAgentSkills.fieldNamePlaceholder'), className: "py-6" })] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$1, { htmlFor: "skill-slug", className: "text-sm font-medium text-[#646464]", children: t('clawSandboxAgentSkills.fieldSlug') }), jsx(Input, { id: "skill-slug", name: "skill-slug", value: form.slug, onChange: (e) => onChange({ ...form, slug: e.target.value }), placeholder: t('clawSandboxAgentSkills.fieldSlugPlaceholder'), className: "py-6" })] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$1, { htmlFor: "skill-version", className: "text-sm font-medium text-[#646464]", children: t('clawSandboxAgentSkills.fieldVersion') }), jsx(Input, { id: "skill-version", name: "skill-version", value: form.version, onChange: (e) => onChange({ ...form, version: e.target.value }), placeholder: t('clawSandboxAgentSkills.fieldVersionPlaceholder'), className: "py-6" })] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$1, { htmlFor: "skill-category", className: "text-sm font-medium text-[#646464]", children: t('clawSandboxAgentSkills.fieldCategory') }), jsx(Input, { id: "skill-category", name: "skill-category", value: form.category, onChange: (e) => onChange({ ...form, category: e.target.value }), placeholder: t('clawSandboxAgentSkills.fieldCategoryPlaceholder'), className: "py-6" })] }), jsxs("div", { className: "space-y-2", children: [jsx(Label$1, { htmlFor: "skill-description", className: "text-sm font-medium text-[#646464]", children: t('clawSandboxAgentSkills.fieldDescription') }), jsx(Input, { id: "skill-description", name: "skill-description", value: form.description, onChange: (e) => onChange({ ...form, description: e.target.value }), placeholder: t('clawSandboxAgentSkills.fieldDescriptionPlaceholder'), className: "py-6" })] }), showPrivateToggle && (jsxs("div", { className: "flex items-center justify-between rounded-lg border p-4", children: [jsxs("div", { className: "space-y-1", children: [jsx(Label$1, { htmlFor: "skill-private", className: "text-sm font-medium text-[#646464]", children: t('clawSandboxAgentSkills.privateToAgent') }), jsx("p", { className: "text-xs text-gray-500", children: t('clawSandboxAgentSkills.privateToAgentHint') })] }), jsx(Switch, { id: "skill-private", checked: form.privateToAgent, onCheckedChange: (checked) => onChange({ ...form, privateToAgent: checked }), className: "cursor-pointer data-[state=checked]:bg-blue-500" })] })), jsxs("div", { className: "space-y-2 overflow-hidden", children: [jsx(Label$1, { htmlFor: "skill-instruction", className: "text-sm font-medium text-[#646464]", children: t('clawSandboxAgentSkills.fieldInstruction') }), jsx("p", { className: "text-xs text-gray-500", children: t('clawSandboxAgentSkills.instructionHint') }), jsx(RichTextEditor, { value: form.instruction, onChange: (value) => onChange({ ...form, instruction: value }) })] })] }));
|
|
253133
|
+
}
|
|
253134
|
+
|
|
253135
|
+
/** Distance (px) from the list bottom at which the next page is requested. */
|
|
253136
|
+
const LOAD_MORE_THRESHOLD_PX = 48;
|
|
253137
|
+
/**
|
|
253138
|
+
* Listbox half of the chat `/` skill combobox. The composer textarea owns
|
|
253139
|
+
* focus and keyboard handling (see `useSlashSkillPicker`); options here are
|
|
253140
|
+
* referenced via `aria-activedescendant` and selected on click. Scrolling
|
|
253141
|
+
* near the bottom lazily loads the next page of skills.
|
|
253142
|
+
*/
|
|
253143
|
+
function SlashSkillPicker({ skills, activeIndex, listboxId, onSelect, onActiveIndexChange, isLoading = false, isFetchingMore = false, hasMore = false, onLoadMore, }) {
|
|
253144
|
+
const t = useT();
|
|
253145
|
+
const listRef = useRef(null);
|
|
253146
|
+
// Keep the active option scrolled into view during arrow-key browsing.
|
|
253147
|
+
useEffect(() => {
|
|
253148
|
+
var _a;
|
|
253149
|
+
const option = (_a = listRef.current) === null || _a === void 0 ? void 0 : _a.children[activeIndex];
|
|
253150
|
+
option === null || option === void 0 ? void 0 : option.scrollIntoView({ block: 'nearest' });
|
|
253151
|
+
}, [activeIndex]);
|
|
253152
|
+
if (skills.length === 0 && !isLoading)
|
|
253153
|
+
return null;
|
|
253154
|
+
const handleScroll = (event) => {
|
|
253155
|
+
if (!hasMore || isFetchingMore || !onLoadMore)
|
|
253156
|
+
return;
|
|
253157
|
+
const el = event.currentTarget;
|
|
253158
|
+
if (el.scrollTop + el.clientHeight >= el.scrollHeight - LOAD_MORE_THRESHOLD_PX) {
|
|
253159
|
+
onLoadMore();
|
|
253160
|
+
}
|
|
253161
|
+
};
|
|
253162
|
+
return (jsxs("div", { className: "absolute right-0 bottom-full left-0 z-50 mb-2", children: [jsx("div", { "aria-live": "polite", className: "sr-only", children: isLoading
|
|
253163
|
+
? t('slashSkillPicker.loading')
|
|
253164
|
+
: t('slashSkillPicker.resultsAnnouncement', { count: skills.length }) }), isLoading ? (jsxs("div", { role: "status", className: "flex items-center gap-2 rounded-xl border border-gray-200 bg-white px-3 py-3 shadow-lg", "data-testid": "slash-skill-picker-loading", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin text-blue-500" }), jsx("span", { className: "text-sm text-gray-500", children: t('slashSkillPicker.loading') })] })) : (jsxs("ul", { ref: listRef, id: listboxId, role: "listbox", "aria-label": t('slashSkillPicker.listLabel'), onScroll: handleScroll, className: "max-h-64 overflow-y-auto rounded-xl border border-gray-200 bg-white p-1 shadow-lg", "data-testid": "slash-skill-picker", children: [skills.map((skill, index) => (jsxs("li", { id: `${listboxId}-option-${index}`, role: "option", "aria-selected": index === activeIndex, className: cn('flex cursor-pointer flex-col gap-0.5 rounded-lg px-3 py-2', index === activeIndex ? 'bg-blue-50' : 'hover:bg-gray-50'), onMouseEnter: () => onActiveIndexChange(index),
|
|
253165
|
+
// onMouseDown so selection wins over the textarea losing focus.
|
|
253166
|
+
onMouseDown: (e) => {
|
|
253167
|
+
e.preventDefault();
|
|
253168
|
+
onSelect(skill);
|
|
253169
|
+
}, children: [jsxs("span", { className: "flex items-baseline gap-2", children: [jsx("span", { className: "text-sm font-medium text-gray-800", children: skill.name }), jsxs("span", { className: "text-xs text-gray-400", children: ["/", skill.slug] }), skill.category && (jsx("span", { className: "ml-auto rounded-full bg-gray-100 px-2 py-0.5 text-[0.625rem] text-gray-500", children: skill.category }))] }), skill.description && (jsx("span", { className: "line-clamp-2 text-xs text-gray-500", children: skill.description }))] }, skill.unique_id))), isFetchingMore && (jsxs("li", { role: "presentation", className: "flex items-center gap-2 px-3 py-2", "data-testid": "slash-skill-picker-loading-more", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin text-blue-500" }), jsx("span", { className: "text-xs text-gray-500", children: t('slashSkillPicker.loading') })] }))] }))] }));
|
|
253170
|
+
}
|
|
253171
|
+
|
|
253172
|
+
/** Matches a composer value that is a single `/`-prefixed token (no whitespace). */
|
|
253173
|
+
const SLASH_TOKEN_RE = /^\/\S*$/;
|
|
253174
|
+
/**
|
|
253175
|
+
* State machine for the chat `/` skill picker. Opens while the composer holds
|
|
253176
|
+
* a single `/`-prefixed token and at least one enabled skill matches; `Esc`
|
|
253177
|
+
* dismisses until the token is cleared, so plain text starting with `/` is
|
|
253178
|
+
* never blocked.
|
|
253179
|
+
*/
|
|
253180
|
+
function useSlashSkillPicker({ inputValue, setInputValue, skills, isLoading = false, }) {
|
|
253181
|
+
const listboxId = useId$2();
|
|
253182
|
+
const [dismissed, setDismissed] = useState(false);
|
|
253183
|
+
const [activeIndex, setActiveIndex] = useState(0);
|
|
253184
|
+
const isSlashToken = SLASH_TOKEN_RE.test(inputValue);
|
|
253185
|
+
const query = isSlashToken ? inputValue.slice(1) : '';
|
|
253186
|
+
const filteredSkills = useMemo(() => (isSlashToken ? filterSlashSkills(skills, query) : []), [isSlashToken, skills, query]);
|
|
253187
|
+
// Loading keeps the picker open (with a loading row) so the user knows
|
|
253188
|
+
// something is coming; once loaded, zero matches closes it.
|
|
253189
|
+
const open = isSlashToken && !dismissed && (filteredSkills.length > 0 || isLoading);
|
|
253190
|
+
// Re-arm the picker once the slash token is gone (text sent or cleared).
|
|
253191
|
+
useEffect(() => {
|
|
253192
|
+
if (!isSlashToken && dismissed)
|
|
253193
|
+
setDismissed(false);
|
|
253194
|
+
}, [isSlashToken, dismissed]);
|
|
253195
|
+
// Keep the active option valid as the query narrows the list.
|
|
253196
|
+
const filteredLength = filteredSkills.length;
|
|
253197
|
+
const previousLength = useRef(filteredLength);
|
|
253198
|
+
useEffect(() => {
|
|
253199
|
+
if (previousLength.current !== filteredLength) {
|
|
253200
|
+
previousLength.current = filteredLength;
|
|
253201
|
+
setActiveIndex(0);
|
|
253202
|
+
}
|
|
253203
|
+
}, [filteredLength]);
|
|
253204
|
+
const selectSkill = (skill) => {
|
|
253205
|
+
setInputValue(`/${skill.slug} `);
|
|
253206
|
+
setActiveIndex(0);
|
|
253207
|
+
};
|
|
253208
|
+
const handleKeyDown = (event) => {
|
|
253209
|
+
if (!open)
|
|
253210
|
+
return false;
|
|
253211
|
+
switch (event.key) {
|
|
253212
|
+
case 'ArrowDown':
|
|
253213
|
+
if (!filteredSkills.length)
|
|
253214
|
+
return false;
|
|
253215
|
+
event.preventDefault();
|
|
253216
|
+
setActiveIndex((index) => (index + 1) % filteredSkills.length);
|
|
253217
|
+
return true;
|
|
253218
|
+
case 'ArrowUp':
|
|
253219
|
+
if (!filteredSkills.length)
|
|
253220
|
+
return false;
|
|
253221
|
+
event.preventDefault();
|
|
253222
|
+
setActiveIndex((index) => (index - 1 + filteredSkills.length) % filteredSkills.length);
|
|
253223
|
+
return true;
|
|
253224
|
+
case 'Enter':
|
|
253225
|
+
if (event.shiftKey || !filteredSkills.length)
|
|
253226
|
+
return false;
|
|
253227
|
+
event.preventDefault();
|
|
253228
|
+
selectSkill(filteredSkills[activeIndex]);
|
|
253229
|
+
return true;
|
|
253230
|
+
case 'Tab':
|
|
253231
|
+
if (!filteredSkills.length)
|
|
253232
|
+
return false;
|
|
253233
|
+
event.preventDefault();
|
|
253234
|
+
selectSkill(filteredSkills[activeIndex]);
|
|
253235
|
+
return true;
|
|
253236
|
+
case 'Escape':
|
|
253237
|
+
event.preventDefault();
|
|
253238
|
+
setDismissed(true);
|
|
253239
|
+
return true;
|
|
253240
|
+
default:
|
|
253241
|
+
return false;
|
|
253242
|
+
}
|
|
253243
|
+
};
|
|
253244
|
+
return {
|
|
253245
|
+
open,
|
|
253246
|
+
filteredSkills,
|
|
253247
|
+
activeIndex,
|
|
253248
|
+
setActiveIndex,
|
|
253249
|
+
listboxId,
|
|
253250
|
+
activeOptionId: open && filteredSkills.length > 0 ? `${listboxId}-option-${activeIndex}` : undefined,
|
|
253251
|
+
selectSkill,
|
|
253252
|
+
handleKeyDown,
|
|
253253
|
+
};
|
|
253254
|
+
}
|
|
253255
|
+
|
|
252995
253256
|
function c$3(e,u,c){var i=this,a=useRef(null),o=useRef(0),f=useRef(null),l=useRef([]),v=useRef(),m=useRef(),d=useRef(e),g=useRef(true);d.current=e;var p="undefined"!=typeof window,w=!u&&0!==u&&p;if("function"!=typeof e)throw new TypeError("Expected a function");u=+u||0;var s=!!(c=c||{}).leading,x=!("trailing"in c)||!!c.trailing,h="maxWait"in c,y="debounceOnServer"in c&&!!c.debounceOnServer,F=h?Math.max(+c.maxWait||0,u):null;useEffect(function(){return g.current=true,function(){g.current=false;}},[]);var A=useMemo(function(){var r=function(r){var n=l.current,t=v.current;return l.current=v.current=null,o.current=r,m.current=d.current.apply(t,n)},n=function(r,n){w&&cancelAnimationFrame(f.current),f.current=w?requestAnimationFrame(r):setTimeout(r,n);},t=function(r){if(!g.current)return false;var n=r-a.current;return !a.current||n>=u||n<0||h&&r-o.current>=F},e=function(n){return f.current=null,x&&l.current?r(n):(l.current=v.current=null,m.current)},c=function r(){var c=Date.now();if(t(c))return e(c);if(g.current){var i=u-(c-a.current),f=h?Math.min(i,F-(c-o.current)):i;n(r,f);}},A=function(){if(p||y){var e=Date.now(),d=t(e);if(l.current=[].slice.call(arguments),v.current=i,a.current=e,d){if(!f.current&&g.current)return o.current=a.current,n(c,u),s?r(a.current):m.current;if(h)return n(c,u),r(a.current)}return f.current||n(c,u),m.current}};return A.cancel=function(){f.current&&(w?cancelAnimationFrame(f.current):clearTimeout(f.current)),o.current=0,l.current=a.current=v.current=f.current=null;},A.isPending=function(){return !!f.current},A.flush=function(){return f.current?e(Date.now()):m.current},A},[s,h,u,F,x,w,p,y]);return A}function i$8(r,n){return r===n}function a$3(n,t,a){var o=i$8,f=useRef(n),l=useState({})[1],v=c$3(useCallback(function(r){f.current=r,l({});},[l]),t,a),m=useRef(n);return o(m.current,n)||(v(n),m.current=n),[f.current,v]}
|
|
252996
253257
|
|
|
252997
253258
|
lazy(() => Promise.resolve().then(function () { return createProjectModal; }).then((mod) => ({
|
|
@@ -253699,7 +253960,7 @@ const CSS_CLASS_NAMES = {
|
|
|
253699
253960
|
},
|
|
253700
253961
|
};
|
|
253701
253962
|
|
|
253702
|
-
const AutoResizeTextarea = ({ allowEmptySubmit = false, value, onChange, onSubmit, disabled = false, placeholder = '', sessionId = null, isPreviewMode = false, textAreaRows = 3, className = '', style = {}, allowAnonymousAccess = false, embedMode = false, ...props }) => {
|
|
253963
|
+
const AutoResizeTextarea = ({ allowEmptySubmit = false, value, onChange, onSubmit, onComposerKeyDown, disabled = false, placeholder = '', sessionId = null, isPreviewMode = false, textAreaRows = 3, className = '', style = {}, allowAnonymousAccess = false, embedMode = false, ...props }) => {
|
|
253703
253964
|
const textareaRef = useRef(null);
|
|
253704
253965
|
const [isResizing, setIsResizing] = useState(false);
|
|
253705
253966
|
const numberOfMessages = useSelector(selectNumberOfActiveChatMessages);
|
|
@@ -253747,6 +254008,8 @@ const AutoResizeTextarea = ({ allowEmptySubmit = false, value, onChange, onSubmi
|
|
|
253747
254008
|
const handleKeyDown = (e) => {
|
|
253748
254009
|
if (isPreviewMode && !allowAnonymousAccess)
|
|
253749
254010
|
return;
|
|
254011
|
+
if (onComposerKeyDown === null || onComposerKeyDown === void 0 ? void 0 : onComposerKeyDown(e))
|
|
254012
|
+
return;
|
|
253750
254013
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
253751
254014
|
e.preventDefault();
|
|
253752
254015
|
if (value.trim() || allowEmptySubmit) {
|
|
@@ -254021,8 +254284,501 @@ function MemoryButton({ mentorId, tenantKey, username }) {
|
|
|
254021
254284
|
} }))] }) }), jsx(PopoverContent, { className: "w-96 rounded-lg border border-gray-200 bg-white p-0 shadow-xl", children: jsx(MemoryMenu, { onClose: () => setIsOpen(false), mentorId: mentorId, tenantKey: tenantKey, username: username }) })] }));
|
|
254022
254285
|
}
|
|
254023
254286
|
|
|
254287
|
+
// Tauri types for model download functionality
|
|
254288
|
+
/**
|
|
254289
|
+
* Initial state for model download
|
|
254290
|
+
*/
|
|
254291
|
+
const initialModelDownloadState = {
|
|
254292
|
+
status: 'idle',
|
|
254293
|
+
progress: 0,
|
|
254294
|
+
message: '',
|
|
254295
|
+
logs: [],
|
|
254296
|
+
lastUpdated: new Date().toISOString(),
|
|
254297
|
+
};
|
|
254298
|
+
/**
|
|
254299
|
+
* Check if the app is running inside Tauri
|
|
254300
|
+
* In Tauri 2.0, the global is __TAURI_INTERNALS__ (with withGlobalTauri: true)
|
|
254301
|
+
* We also check for __TAURI__ for backwards compatibility
|
|
254302
|
+
*/
|
|
254303
|
+
const isTauriApp$1 = () => {
|
|
254304
|
+
if (typeof window === 'undefined')
|
|
254305
|
+
return false;
|
|
254306
|
+
return '__TAURI_INTERNALS__' in window || '__TAURI__' in window;
|
|
254307
|
+
};
|
|
254308
|
+
/**
|
|
254309
|
+
* Tauri event names
|
|
254310
|
+
*/
|
|
254311
|
+
const TAURI_EVENTS = {
|
|
254312
|
+
DOWNLOAD_PROGRESS: 'model:download-progress',
|
|
254313
|
+
INSTALLATION_LOG: 'model:installation-log',
|
|
254314
|
+
DISK_SPACE_ERROR: 'model:disk-space-error',
|
|
254315
|
+
OLLAMA_STATUS: 'model:ollama-status',
|
|
254316
|
+
};
|
|
254317
|
+
/**
|
|
254318
|
+
* Tauri command names
|
|
254319
|
+
*/
|
|
254320
|
+
const TAURI_COMMANDS = {
|
|
254321
|
+
INSTALL_OLLAMA: 'install_ollama',
|
|
254322
|
+
STOP_OLLAMA: 'stop_ollama',
|
|
254323
|
+
CHECK_OLLAMA_STATUS: 'check_ollama_status',
|
|
254324
|
+
CHECK_DISK_SPACE: 'check_disk_space_for_model',
|
|
254325
|
+
GET_SYSTEM_MEMORY: 'get_system_memory',
|
|
254326
|
+
DOWNLOAD_MODEL: 'download_model',
|
|
254327
|
+
CANCEL_DOWNLOAD: 'cancel_model_download',
|
|
254328
|
+
CHECK_NETWORK_STATUS: 'check_network_status',
|
|
254329
|
+
GET_OS_TYPE: 'get_os_type',
|
|
254330
|
+
CHECK_FOUNDRY_STATUS: 'check_foundry_local_status',
|
|
254331
|
+
START_FOUNDRY_SERVICE: 'start_foundry_local_service',
|
|
254332
|
+
LOAD_FOUNDRY_MODEL: 'load_foundry_local_model',
|
|
254333
|
+
SET_SELECTED_FOUNDRY_MODEL: 'set_selected_foundry_model',
|
|
254334
|
+
GET_SELECTED_FOUNDRY_MODEL: 'get_selected_foundry_model',
|
|
254335
|
+
INSTALL_FOUNDRY: 'install_foundry',
|
|
254336
|
+
DOWNLOAD_FOUNDRY_MODEL: 'download_foundry_model_cmd',
|
|
254337
|
+
GET_RECOMMENDED_FOUNDRY_MODELS: 'get_recommended_foundry_models',
|
|
254338
|
+
LOG_STDOUT: 'log_stdout',
|
|
254339
|
+
};
|
|
254340
|
+
/**
|
|
254341
|
+
* Initial state for the Cowork install flow.
|
|
254342
|
+
*/
|
|
254343
|
+
const initialGhostOsInstallState = {
|
|
254344
|
+
status: 'idle',
|
|
254345
|
+
progress: 0,
|
|
254346
|
+
message: '',
|
|
254347
|
+
logs: [],
|
|
254348
|
+
lastUpdated: new Date().toISOString(),
|
|
254349
|
+
};
|
|
254350
|
+
/**
|
|
254351
|
+
* Tauri event names emitted by the host during GhostOS install/setup.
|
|
254352
|
+
*/
|
|
254353
|
+
const GHOST_OS_TAURI_EVENTS = {
|
|
254354
|
+
INSTALL_PROGRESS: 'ghost-os:install-progress',
|
|
254355
|
+
INSTALLATION_LOG: 'ghost-os:installation-log',
|
|
254356
|
+
STATUS: 'ghost-os:status',
|
|
254357
|
+
};
|
|
254358
|
+
/**
|
|
254359
|
+
* Tauri command names the host implements for GhostOS install/setup. The web
|
|
254360
|
+
* layer invokes these; the native side performs the clone + setup.
|
|
254361
|
+
*/
|
|
254362
|
+
const GHOST_OS_TAURI_COMMANDS = {
|
|
254363
|
+
/** Install and set up GhostOS (clone repo + run setup). */
|
|
254364
|
+
INSTALL_GHOST_OS: 'install_ghost_os',
|
|
254365
|
+
/** Stop the running GhostOS manager. */
|
|
254366
|
+
STOP_GHOST_OS: 'stop_ghost_os',
|
|
254367
|
+
/** Report current {@link GhostOsStatus}. */
|
|
254368
|
+
CHECK_GHOST_OS_STATUS: 'check_ghost_os_status',
|
|
254369
|
+
};
|
|
254370
|
+
/**
|
|
254371
|
+
* Tauri command strings exposed by `tauri-plugin-macos-permissions`
|
|
254372
|
+
* (https://github.com/ayangweb/tauri-plugin-macos-permissions). GhostOS needs
|
|
254373
|
+
* macOS Accessibility permission to control the device, so the Cowork
|
|
254374
|
+
* card surfaces it. These are invoked directly via `useTauri().invoke(...)` —
|
|
254375
|
+
* no extra npm dependency. The host must register the plugin in its Tauri app
|
|
254376
|
+
* (`tauri_plugin_macos_permissions::init()`). Each `CHECK_*` returns a boolean;
|
|
254377
|
+
* each `REQUEST_*` prompts / opens the relevant System Settings pane.
|
|
254378
|
+
*/
|
|
254379
|
+
const MACOS_PERMISSIONS_COMMANDS = {
|
|
254380
|
+
CHECK_ACCESSIBILITY: 'plugin:macos-permissions|check_accessibility_permission',
|
|
254381
|
+
REQUEST_ACCESSIBILITY: 'plugin:macos-permissions|request_accessibility_permission',
|
|
254382
|
+
CHECK_SCREEN_RECORDING: 'plugin:macos-permissions|check_screen_recording_permission',
|
|
254383
|
+
REQUEST_SCREEN_RECORDING: 'plugin:macos-permissions|request_screen_recording_permission',
|
|
254384
|
+
CHECK_INPUT_MONITORING: 'plugin:macos-permissions|check_input_monitoring_permission',
|
|
254385
|
+
REQUEST_INPUT_MONITORING: 'plugin:macos-permissions|request_input_monitoring_permission',
|
|
254386
|
+
CHECK_FULL_DISK_ACCESS: 'plugin:macos-permissions|check_full_disk_access_permission',
|
|
254387
|
+
REQUEST_FULL_DISK_ACCESS: 'plugin:macos-permissions|request_full_disk_access_permission',
|
|
254388
|
+
};
|
|
254389
|
+
|
|
254390
|
+
/**
|
|
254391
|
+
* Dynamically import Tauri APIs to avoid SSR issues
|
|
254392
|
+
*/
|
|
254393
|
+
const getTauriAPIs = async () => {
|
|
254394
|
+
try {
|
|
254395
|
+
const { invoke } = await import('@tauri-apps/api/core');
|
|
254396
|
+
const { listen } = await import('@tauri-apps/api/event');
|
|
254397
|
+
return { invoke, listen };
|
|
254398
|
+
}
|
|
254399
|
+
catch (error) {
|
|
254400
|
+
console.error('Failed to load Tauri APIs:', error);
|
|
254401
|
+
return null;
|
|
254402
|
+
}
|
|
254403
|
+
};
|
|
254404
|
+
/**
|
|
254405
|
+
* Hook to access Tauri APIs with SSR safety
|
|
254406
|
+
*
|
|
254407
|
+
* @returns Object with isAvailable flag and Tauri invoke/listen functions
|
|
254408
|
+
*/
|
|
254409
|
+
function useTauri() {
|
|
254410
|
+
const [isAvailable, setIsAvailable] = useState(false);
|
|
254411
|
+
const [apis, setApis] = useState(null);
|
|
254412
|
+
useEffect(() => {
|
|
254413
|
+
// Check if we're in a Tauri environment
|
|
254414
|
+
const inTauri = isTauriApp$1();
|
|
254415
|
+
if (inTauri) {
|
|
254416
|
+
getTauriAPIs().then((result) => {
|
|
254417
|
+
setApis(result);
|
|
254418
|
+
setIsAvailable(!!result);
|
|
254419
|
+
});
|
|
254420
|
+
}
|
|
254421
|
+
}, []);
|
|
254422
|
+
/**
|
|
254423
|
+
* Invoke a Tauri command
|
|
254424
|
+
*/
|
|
254425
|
+
const invoke = useCallback(async (command, args) => {
|
|
254426
|
+
if (!(apis === null || apis === void 0 ? void 0 : apis.invoke)) {
|
|
254427
|
+
throw new Error('Tauri is not available');
|
|
254428
|
+
}
|
|
254429
|
+
return apis.invoke(command, args);
|
|
254430
|
+
}, [apis]);
|
|
254431
|
+
/**
|
|
254432
|
+
* Listen to a Tauri event
|
|
254433
|
+
* Returns an unlisten function that should be called on cleanup
|
|
254434
|
+
*/
|
|
254435
|
+
const listen = useCallback(async (event, handler) => {
|
|
254436
|
+
// The synchronous global (`__TAURI_INTERNALS__`) exposes `invoke` but
|
|
254437
|
+
// frequently NOT `event.listen`, so `apis.listen` can be undefined even
|
|
254438
|
+
// though Tauri is fully available. Fall back to the real event API via
|
|
254439
|
+
// dynamic import so download progress/completion events are actually
|
|
254440
|
+
// delivered — otherwise the UI never leaves the "downloading" state.
|
|
254441
|
+
let listenFn = apis === null || apis === void 0 ? void 0 : apis.listen;
|
|
254442
|
+
if (!listenFn) {
|
|
254443
|
+
const { listen: importedListen } = await import('@tauri-apps/api/event');
|
|
254444
|
+
listenFn = importedListen;
|
|
254445
|
+
}
|
|
254446
|
+
return listenFn(event, (e) => handler(e.payload));
|
|
254447
|
+
}, [apis]);
|
|
254448
|
+
return {
|
|
254449
|
+
isAvailable,
|
|
254450
|
+
invoke,
|
|
254451
|
+
listen,
|
|
254452
|
+
};
|
|
254453
|
+
}
|
|
254454
|
+
|
|
254455
|
+
const IS_SERVER = typeof window === 'undefined';
|
|
254456
|
+
/**
|
|
254457
|
+
* A simplified useLocalStorage hook for persisting state to localStorage
|
|
254458
|
+
* with SSR safety.
|
|
254459
|
+
*/
|
|
254460
|
+
function useLocalStorage(key, initialValue) {
|
|
254461
|
+
// Get the initial value
|
|
254462
|
+
const getInitialValue = useCallback(() => {
|
|
254463
|
+
const initial = initialValue instanceof Function ? initialValue() : initialValue;
|
|
254464
|
+
if (IS_SERVER) {
|
|
254465
|
+
return initial;
|
|
254466
|
+
}
|
|
254467
|
+
try {
|
|
254468
|
+
const item = window.localStorage.getItem(key);
|
|
254469
|
+
if (item === null) {
|
|
254470
|
+
return initial;
|
|
254471
|
+
}
|
|
254472
|
+
return JSON.parse(item);
|
|
254473
|
+
}
|
|
254474
|
+
catch (error) {
|
|
254475
|
+
console.warn(`Error reading localStorage key "${key}":`, error);
|
|
254476
|
+
return initial;
|
|
254477
|
+
}
|
|
254478
|
+
}, [key, initialValue]);
|
|
254479
|
+
const [storedValue, setStoredValue] = useState(getInitialValue);
|
|
254480
|
+
// Update stored value when key changes
|
|
254481
|
+
useEffect(() => {
|
|
254482
|
+
setStoredValue(getInitialValue());
|
|
254483
|
+
}, [key, getInitialValue]);
|
|
254484
|
+
// Persist to localStorage
|
|
254485
|
+
const setValue = useCallback((value) => {
|
|
254486
|
+
if (IS_SERVER) {
|
|
254487
|
+
console.warn(`Tried setting localStorage key "${key}" even though environment is not a client`);
|
|
254488
|
+
return;
|
|
254489
|
+
}
|
|
254490
|
+
try {
|
|
254491
|
+
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
|
254492
|
+
setStoredValue(valueToStore);
|
|
254493
|
+
window.localStorage.setItem(key, JSON.stringify(valueToStore));
|
|
254494
|
+
}
|
|
254495
|
+
catch (error) {
|
|
254496
|
+
console.warn(`Error setting localStorage key "${key}":`, error);
|
|
254497
|
+
}
|
|
254498
|
+
}, [key, storedValue]);
|
|
254499
|
+
// Remove from localStorage
|
|
254500
|
+
const removeValue = useCallback(() => {
|
|
254501
|
+
if (IS_SERVER) {
|
|
254502
|
+
console.warn(`Tried removing localStorage key "${key}" even though environment is not a client`);
|
|
254503
|
+
return;
|
|
254504
|
+
}
|
|
254505
|
+
try {
|
|
254506
|
+
const initial = initialValue instanceof Function ? initialValue() : initialValue;
|
|
254507
|
+
window.localStorage.removeItem(key);
|
|
254508
|
+
setStoredValue(initial);
|
|
254509
|
+
}
|
|
254510
|
+
catch (error) {
|
|
254511
|
+
console.warn(`Error removing localStorage key "${key}":`, error);
|
|
254512
|
+
}
|
|
254513
|
+
}, [key, initialValue]);
|
|
254514
|
+
return [storedValue, setValue, removeValue];
|
|
254515
|
+
}
|
|
254516
|
+
|
|
254517
|
+
const LOCAL_STORAGE_KEY$1 = 'ghost_os_install_state';
|
|
254518
|
+
/**
|
|
254519
|
+
* Manage installing & setting up GhostOS (https://github.com/ghostwright/ghost-os)
|
|
254520
|
+
* via the Tauri host. This is the self-contained backing hook for the System
|
|
254521
|
+
* Control card and deliberately mirrors `useModelDownload`:
|
|
254522
|
+
*
|
|
254523
|
+
* - checks GhostOS install/run status through the host
|
|
254524
|
+
* - installs/sets up GhostOS with real-time progress + logs
|
|
254525
|
+
* - persists state across app restarts
|
|
254526
|
+
*
|
|
254527
|
+
* Outside the desktop (Tauri) app every action is a no-op and `isAvailable` is
|
|
254528
|
+
* false, so the card hides itself.
|
|
254529
|
+
*/
|
|
254530
|
+
function useGhostOs() {
|
|
254531
|
+
const { isAvailable, invoke, listen } = useTauri();
|
|
254532
|
+
const [state, setState] = useLocalStorage(LOCAL_STORAGE_KEY$1, initialGhostOsInstallState);
|
|
254533
|
+
const [status, setStatus] = useState(null);
|
|
254534
|
+
// macOS Accessibility permission, which GhostOS needs to control the device.
|
|
254535
|
+
// null = unknown/not-yet-checked or unsupported (non-macOS / plugin absent).
|
|
254536
|
+
const [accessibilityPermission, setAccessibilityPermission] = useState(null);
|
|
254537
|
+
const unlistenRefs = useRef([]);
|
|
254538
|
+
const hasCheckedStatus = useRef(false);
|
|
254539
|
+
/**
|
|
254540
|
+
* Refresh the macOS Accessibility permission via tauri-plugin-macos-permissions.
|
|
254541
|
+
* Independent of the GhostOS status check so a missing host command for one
|
|
254542
|
+
* doesn't suppress the other. Stays null where unsupported.
|
|
254543
|
+
*/
|
|
254544
|
+
const refreshAccessibilityPermission = useCallback(async () => {
|
|
254545
|
+
if (!isAvailable)
|
|
254546
|
+
return;
|
|
254547
|
+
try {
|
|
254548
|
+
const granted = await invoke(MACOS_PERMISSIONS_COMMANDS.CHECK_ACCESSIBILITY);
|
|
254549
|
+
setAccessibilityPermission(granted);
|
|
254550
|
+
}
|
|
254551
|
+
catch (error) {
|
|
254552
|
+
// Plugin not registered or non-macOS host — leave permission unknown.
|
|
254553
|
+
console.warn('[useGhostOs] Accessibility permission check unavailable:', error);
|
|
254554
|
+
setAccessibilityPermission(null);
|
|
254555
|
+
}
|
|
254556
|
+
}, [isAvailable, invoke]);
|
|
254557
|
+
/**
|
|
254558
|
+
* Open the Accessibility pane / prompt so the user can grant permission, then
|
|
254559
|
+
* re-check (the grant happens in System Settings, so we refresh after).
|
|
254560
|
+
*/
|
|
254561
|
+
const requestAccessibilityPermission = useCallback(async () => {
|
|
254562
|
+
if (!isAvailable)
|
|
254563
|
+
return;
|
|
254564
|
+
try {
|
|
254565
|
+
await invoke(MACOS_PERMISSIONS_COMMANDS.REQUEST_ACCESSIBILITY);
|
|
254566
|
+
}
|
|
254567
|
+
catch (error) {
|
|
254568
|
+
console.error('[useGhostOs] Failed to request accessibility permission:', error);
|
|
254569
|
+
}
|
|
254570
|
+
await refreshAccessibilityPermission();
|
|
254571
|
+
}, [isAvailable, invoke, refreshAccessibilityPermission]);
|
|
254572
|
+
const addLog = useCallback((log) => {
|
|
254573
|
+
setState((prev) => ({
|
|
254574
|
+
...prev,
|
|
254575
|
+
logs: [...prev.logs.slice(-99), log],
|
|
254576
|
+
lastUpdated: new Date().toISOString(),
|
|
254577
|
+
}));
|
|
254578
|
+
}, [setState]);
|
|
254579
|
+
/**
|
|
254580
|
+
* Query GhostOS status from the host.
|
|
254581
|
+
*/
|
|
254582
|
+
const checkStatus = useCallback(async () => {
|
|
254583
|
+
if (!isAvailable)
|
|
254584
|
+
return;
|
|
254585
|
+
// Refresh the accessibility permission alongside install status (independent).
|
|
254586
|
+
refreshAccessibilityPermission();
|
|
254587
|
+
try {
|
|
254588
|
+
setState((prev) => ({ ...prev, status: 'checking' }));
|
|
254589
|
+
const result = await invoke(GHOST_OS_TAURI_COMMANDS.CHECK_GHOST_OS_STATUS);
|
|
254590
|
+
setStatus(result);
|
|
254591
|
+
setState((prev) => ({
|
|
254592
|
+
...prev,
|
|
254593
|
+
status: result.installed ? 'completed' : 'idle',
|
|
254594
|
+
progress: result.installed ? 100 : prev.progress,
|
|
254595
|
+
lastUpdated: new Date().toISOString(),
|
|
254596
|
+
}));
|
|
254597
|
+
}
|
|
254598
|
+
catch (error) {
|
|
254599
|
+
console.error('[useGhostOs] Failed to check status:', error);
|
|
254600
|
+
setState((prev) => ({ ...prev, status: 'idle' }));
|
|
254601
|
+
}
|
|
254602
|
+
}, [isAvailable, invoke, setState, refreshAccessibilityPermission]);
|
|
254603
|
+
/**
|
|
254604
|
+
* Install and set up GhostOS. The host clones the repo + runs setup and emits
|
|
254605
|
+
* progress/log/status events along the way.
|
|
254606
|
+
*/
|
|
254607
|
+
const install = useCallback(async () => {
|
|
254608
|
+
if (!isAvailable)
|
|
254609
|
+
return;
|
|
254610
|
+
try {
|
|
254611
|
+
setState((prev) => ({
|
|
254612
|
+
...prev,
|
|
254613
|
+
status: 'installing',
|
|
254614
|
+
progress: 0,
|
|
254615
|
+
message: 'Setting up your assistant…',
|
|
254616
|
+
error: undefined,
|
|
254617
|
+
logs: [],
|
|
254618
|
+
}));
|
|
254619
|
+
addLog({
|
|
254620
|
+
timestamp: new Date().toISOString(),
|
|
254621
|
+
level: 'info',
|
|
254622
|
+
message: 'Starting setup…',
|
|
254623
|
+
});
|
|
254624
|
+
const result = await invoke(GHOST_OS_TAURI_COMMANDS.INSTALL_GHOST_OS);
|
|
254625
|
+
addLog({
|
|
254626
|
+
timestamp: new Date().toISOString(),
|
|
254627
|
+
level: 'info',
|
|
254628
|
+
message: typeof result === 'string' && result ? result : 'Setup complete',
|
|
254629
|
+
});
|
|
254630
|
+
setState((prev) => ({
|
|
254631
|
+
...prev,
|
|
254632
|
+
status: 'completed',
|
|
254633
|
+
progress: 100,
|
|
254634
|
+
message: 'Your assistant is ready',
|
|
254635
|
+
lastUpdated: new Date().toISOString(),
|
|
254636
|
+
}));
|
|
254637
|
+
await checkStatus();
|
|
254638
|
+
}
|
|
254639
|
+
catch (error) {
|
|
254640
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
254641
|
+
setState((prev) => ({
|
|
254642
|
+
...prev,
|
|
254643
|
+
status: 'error',
|
|
254644
|
+
error: message,
|
|
254645
|
+
message: 'Setup didn’t finish',
|
|
254646
|
+
lastUpdated: new Date().toISOString(),
|
|
254647
|
+
}));
|
|
254648
|
+
addLog({
|
|
254649
|
+
timestamp: new Date().toISOString(),
|
|
254650
|
+
level: 'error',
|
|
254651
|
+
message: `Install failed: ${message}`,
|
|
254652
|
+
});
|
|
254653
|
+
}
|
|
254654
|
+
}, [isAvailable, invoke, addLog, checkStatus, setState]);
|
|
254655
|
+
/**
|
|
254656
|
+
* Stop the running GhostOS manager.
|
|
254657
|
+
*/
|
|
254658
|
+
const stop = useCallback(async () => {
|
|
254659
|
+
if (!isAvailable)
|
|
254660
|
+
return;
|
|
254661
|
+
try {
|
|
254662
|
+
await invoke(GHOST_OS_TAURI_COMMANDS.STOP_GHOST_OS);
|
|
254663
|
+
await checkStatus();
|
|
254664
|
+
}
|
|
254665
|
+
catch (error) {
|
|
254666
|
+
console.error('[useGhostOs] Failed to stop GhostOS:', error);
|
|
254667
|
+
}
|
|
254668
|
+
}, [isAvailable, invoke, checkStatus]);
|
|
254669
|
+
/**
|
|
254670
|
+
* Reset the install state (for retrying after an error).
|
|
254671
|
+
*/
|
|
254672
|
+
const resetState = useCallback(() => {
|
|
254673
|
+
setState(initialGhostOsInstallState);
|
|
254674
|
+
}, [setState]);
|
|
254675
|
+
// Wire up host event listeners (progress / logs / status).
|
|
254676
|
+
useEffect(() => {
|
|
254677
|
+
if (!isAvailable)
|
|
254678
|
+
return;
|
|
254679
|
+
const setupListeners = async () => {
|
|
254680
|
+
try {
|
|
254681
|
+
const unlistenProgress = await listen(GHOST_OS_TAURI_EVENTS.INSTALL_PROGRESS, (payload) => {
|
|
254682
|
+
const nextStatus = payload.status === 'completed'
|
|
254683
|
+
? 'completed'
|
|
254684
|
+
: payload.status === 'cancelled'
|
|
254685
|
+
? 'cancelled'
|
|
254686
|
+
: payload.status === 'error'
|
|
254687
|
+
? 'error'
|
|
254688
|
+
: 'installing';
|
|
254689
|
+
setState((prev) => ({
|
|
254690
|
+
...prev,
|
|
254691
|
+
status: nextStatus,
|
|
254692
|
+
progress: payload.percentage,
|
|
254693
|
+
message: payload.message,
|
|
254694
|
+
lastUpdated: new Date().toISOString(),
|
|
254695
|
+
}));
|
|
254696
|
+
});
|
|
254697
|
+
unlistenRefs.current.push(unlistenProgress);
|
|
254698
|
+
const unlistenLogs = await listen(GHOST_OS_TAURI_EVENTS.INSTALLATION_LOG, addLog);
|
|
254699
|
+
unlistenRefs.current.push(unlistenLogs);
|
|
254700
|
+
const unlistenStatus = await listen(GHOST_OS_TAURI_EVENTS.STATUS, setStatus);
|
|
254701
|
+
unlistenRefs.current.push(unlistenStatus);
|
|
254702
|
+
}
|
|
254703
|
+
catch (error) {
|
|
254704
|
+
console.error('[useGhostOs] Failed to setup event listeners:', error);
|
|
254705
|
+
}
|
|
254706
|
+
};
|
|
254707
|
+
setupListeners();
|
|
254708
|
+
return () => {
|
|
254709
|
+
unlistenRefs.current.forEach((unlisten) => unlisten());
|
|
254710
|
+
unlistenRefs.current = [];
|
|
254711
|
+
};
|
|
254712
|
+
}, [isAvailable, listen, setState, addLog]);
|
|
254713
|
+
// Check status once on mount (in the desktop app).
|
|
254714
|
+
useEffect(() => {
|
|
254715
|
+
if (!isAvailable || hasCheckedStatus.current)
|
|
254716
|
+
return;
|
|
254717
|
+
hasCheckedStatus.current = true;
|
|
254718
|
+
checkStatus();
|
|
254719
|
+
}, [isAvailable, checkStatus]);
|
|
254720
|
+
// Only expose the feature as available inside the desktop (Tauri) app.
|
|
254721
|
+
const finalIsAvailable = isAvailable && isTauriApp$1();
|
|
254722
|
+
return {
|
|
254723
|
+
isAvailable: finalIsAvailable,
|
|
254724
|
+
state,
|
|
254725
|
+
status,
|
|
254726
|
+
accessibilityPermission,
|
|
254727
|
+
install,
|
|
254728
|
+
stop,
|
|
254729
|
+
checkStatus,
|
|
254730
|
+
resetState,
|
|
254731
|
+
requestAccessibilityPermission,
|
|
254732
|
+
};
|
|
254733
|
+
}
|
|
254734
|
+
|
|
254735
|
+
// Cowork is macOS-only in prod; the env flag bypasses the OS check so the
|
|
254736
|
+
// toggle can be exercised on Linux/Windows desktop builds during testing.
|
|
254737
|
+
const isMacOS = () => {
|
|
254738
|
+
if (typeof navigator === 'undefined')
|
|
254739
|
+
return false;
|
|
254740
|
+
return /mac/i.test(navigator.userAgent || '');
|
|
254741
|
+
};
|
|
254742
|
+
const allowNonMacOSCowork = () => process.env.NEXT_PUBLIC_ALLOW_NON_MACOS_COMPUTER_USE_TOGGLE === 'true';
|
|
254743
|
+
// 14GB floor per spec; modelSupportsCowork gates size > gb, so a model of
|
|
254744
|
+
// exactly 14GB is also off (no 14.0GB model in the catalog). Only the local-model
|
|
254745
|
+
// backend needs this; the remote AI has no size requirement.
|
|
254746
|
+
const COWORK_MIN_MODEL_GB = 14;
|
|
254024
254747
|
const InsideButtons = ({ activeOptions, onOptionClick, deepResearch, studyMode, artifactsEnabled, containerWidth, disabled = false, onOpenPromptGallery, embedMode = false, promptsIsEnabled = false, memoryEnabled = false, mentorId, tenantKey, username, }) => {
|
|
254025
254748
|
const t = useT();
|
|
254749
|
+
// Cowork = the Tauri GhostOS assistant. GhostOS runs the tools on-device;
|
|
254750
|
+
// the "brain" is EITHER a large local model (Local Models / Ollama) OR the
|
|
254751
|
+
// remote AI (DM OpenAI-compatible endpoint), whichever is set up. useGhostOs
|
|
254752
|
+
// handles install/stop; the localStorage pref (isCoworkEnabled) is read
|
|
254753
|
+
// by the chat hook to route the turn. Reads the pref on mount.
|
|
254754
|
+
// Local state is `coworkOn` so it doesn't shadow the imported setCoworkEnabled.
|
|
254755
|
+
const ghostOs = useGhostOs();
|
|
254756
|
+
const [coworkOn, setCoworkOn] = useState(isCoworkEnabled);
|
|
254757
|
+
const toggleCowork = () => {
|
|
254758
|
+
const next = !coworkOn;
|
|
254759
|
+
// Guard only when turning on. Cowork runs on either a large local model
|
|
254760
|
+
// or the remote AI — allow enabling when either backend is ready (the local
|
|
254761
|
+
// model + Cowork combo still works). The chatbox has no inline notice
|
|
254762
|
+
// space, so remind via toast. (RBAC is enforced separately: this button is
|
|
254763
|
+
// `disabled` when the user lacks the mentor `#chat` permission — see
|
|
254764
|
+
// chat-input-form's isChatDisabledByRbac.)
|
|
254765
|
+
if (next) {
|
|
254766
|
+
const localReady = isLocalLLMEnabled() &&
|
|
254767
|
+
modelSupportsCowork(getLocalLLMModel(), COWORK_MIN_MODEL_GB);
|
|
254768
|
+
if (!localReady && !hasRemoteAiConfig()) {
|
|
254769
|
+
toast.warning(isLocalLLMEnabled()
|
|
254770
|
+
? t('chatInputFormInsideButtons.coworkModelTooSmall')
|
|
254771
|
+
: t('chatInputFormInsideButtons.coworkNeedsBackend'));
|
|
254772
|
+
return;
|
|
254773
|
+
}
|
|
254774
|
+
}
|
|
254775
|
+
setCoworkOn(next);
|
|
254776
|
+
setCoworkEnabled(next);
|
|
254777
|
+
if (next)
|
|
254778
|
+
ghostOs.install();
|
|
254779
|
+
else
|
|
254780
|
+
ghostOs.stop();
|
|
254781
|
+
};
|
|
254026
254782
|
const allInsideButtons = [
|
|
254027
254783
|
{
|
|
254028
254784
|
name: 'Canvas',
|
|
@@ -254066,6 +254822,14 @@ const InsideButtons = ({ activeOptions, onOptionClick, deepResearch, studyMode,
|
|
|
254066
254822
|
action: /* istanbul ignore next */ () => onOptionClick(TOOLS.MEMORY),
|
|
254067
254823
|
isEnabled: memoryEnabled && !embedMode && !!username,
|
|
254068
254824
|
},
|
|
254825
|
+
{
|
|
254826
|
+
name: 'Cowork',
|
|
254827
|
+
label: t('chatInputFormInsideButtons.cowork'),
|
|
254828
|
+
icon: jsx(Monitor, { className: "h-4 w-4" }),
|
|
254829
|
+
isActive: coworkOn,
|
|
254830
|
+
action: toggleCowork,
|
|
254831
|
+
isEnabled: ghostOs.isAvailable && (isMacOS() || allowNonMacOSCowork()),
|
|
254832
|
+
},
|
|
254069
254833
|
].filter((item) => item.isEnabled);
|
|
254070
254834
|
// Get visible inside buttons based on screen size
|
|
254071
254835
|
// Active buttons are always visible, inactive ones are hidden based on available width
|
|
@@ -254583,7 +255347,7 @@ function SubmitMessageButton({ isPreviewMode, allowAnonymousAccess, isUploading,
|
|
|
254583
255347
|
const PromptGalleryModal$1 = dynamic(() => Promise.resolve().then(function () { return promptGalleryModal; }).then((mod) => mod.PromptGalleryModal), {
|
|
254584
255348
|
ssr: false,
|
|
254585
255349
|
});
|
|
254586
|
-
function ChatInputForm({ onSubmit, onScreenSharingClick, isScreenSharingModalOpen, onPhoneCallClick, sessionId, stopGenerating, mentorId, tenantKey, isPublicRoute, userIsStudent, username, isPreviewMode, enableWebBrowsing, isStreaming, updateSessionTools, setSessionTools, activeTools, screenSharing, deepResearch, studyMode, imageGeneration, codeInterpreter, promptsIsEnabled, googleSlidesIsEnabled, googleDocumentIsEnabled, artifactsEnabled, compactMode = false, chatAreaMaxWidth, isConnecting = false, stopStreamingButtonRef, }) {
|
|
255350
|
+
function ChatInputForm({ onSubmit, onScreenSharingClick, isScreenSharingModalOpen, onPhoneCallClick, sessionId, stopGenerating, mentorId, tenantKey, isPublicRoute, userIsStudent, username, isPreviewMode, enableWebBrowsing, isStreaming, updateSessionTools, setSessionTools, activeTools, screenSharing, deepResearch, studyMode, imageGeneration, codeInterpreter, promptsIsEnabled, googleSlidesIsEnabled, googleDocumentIsEnabled, artifactsEnabled, compactMode = false, chatAreaMaxWidth, isConnecting = false, stopStreamingButtonRef, slashSkills, slashSkillsLoading = false, }) {
|
|
254587
255351
|
var _a, _b, _c, _d, _e;
|
|
254588
255352
|
const t = useT();
|
|
254589
255353
|
const dispatch = useDispatch();
|
|
@@ -254637,6 +255401,15 @@ function ChatInputForm({ onSubmit, onScreenSharingClick, isScreenSharingModalOpe
|
|
|
254637
255401
|
const setInputValue = (input) => {
|
|
254638
255402
|
dispatch(chatInputSliceActions.setTextareaInput(input));
|
|
254639
255403
|
};
|
|
255404
|
+
// `/` skill picker — active only when the host supplies the agent's
|
|
255405
|
+
// effective skills (or reports them loading). No fetching happens here.
|
|
255406
|
+
const effectiveSlashSkills = slashSkills !== null && slashSkills !== void 0 ? slashSkills : [];
|
|
255407
|
+
const slashPicker = useSlashSkillPicker({
|
|
255408
|
+
inputValue,
|
|
255409
|
+
setInputValue,
|
|
255410
|
+
skills: effectiveSlashSkills,
|
|
255411
|
+
isLoading: slashSkillsLoading,
|
|
255412
|
+
});
|
|
254640
255413
|
const handleSelectPrompt = (promptText) => {
|
|
254641
255414
|
setInputValue(promptText);
|
|
254642
255415
|
setIsPromptGalleryOpen(false);
|
|
@@ -254701,9 +255474,18 @@ function ChatInputForm({ onSubmit, onScreenSharingClick, isScreenSharingModalOpe
|
|
|
254701
255474
|
}
|
|
254702
255475
|
return persistentChatInputLabel ? '' : t('chatInputForm.askAnything');
|
|
254703
255476
|
};
|
|
254704
|
-
return (jsxs(Fragment$1, { children: [isTabletOrMobile && !isPreviewMode && !embedMode && !compactMode && (jsx("div", { className: "mx-auto flex w-full justify-end pt-4 pl-4", style: chatAreaMaxWidth ? { maxWidth: `${chatAreaMaxWidth}px` } : undefined, children: jsx(RetrievedDocumentsButton, { sessionId: sessionId }) })), ((_c = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.data) === null || _c === void 0 ? void 0 : _c.disclaimer) && !compactMode && (jsx("div", { className: "mx-auto mt-1 w-full pb-1", style: chatAreaMaxWidth ? { maxWidth: `${chatAreaMaxWidth}px` } : undefined, children: jsx("p", { id: "chat-input-disclaimer", className: "text-center text-[0.625rem] text-gray-500 italic", children: (_d = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.data) === null || _d === void 0 ? void 0 : _d.disclaimer }) })), jsxs("form", { ref: containerRef, onSubmit: handleSubmit, className: cn('mx-auto mt-4 w-full pb-2', CSS_CLASS_NAMES.CHAT.TEXTAREA), style: chatAreaMaxWidth ? { maxWidth: `${chatAreaMaxWidth}px` } : undefined, children: [jsxs("div", { className: "relative overflow-hidden rounded-2xl border border-gray-200 bg-[#fbfbfb] pb-3 shadow-xs", children: [jsx(FileAttachmentsList, { attachedFiles: attachedFiles, onRemoveFile: handleRemoveFile, onRetryFile: retryUpload }), fileAddedNotification && (jsxs("div", { className: "animate-in slide-in-from-bottom-5 absolute top-0 right-0 left-0 -mt-10 flex items-center gap-2 rounded-md bg-blue-50 p-2 text-xs text-blue-600 duration-300", children: [jsx(FileText, { className: "h-3 w-3" }), jsx("span", { className: "truncate", children: fileAddedNotification })] })), jsxs("div", { className: "grid", children: [jsx("label", { id: "chat-input-label", htmlFor: "chat-input-textarea", className: cn(persistentChatInputLabel
|
|
255477
|
+
return (jsxs(Fragment$1, { children: [isTabletOrMobile && !isPreviewMode && !embedMode && !compactMode && (jsx("div", { className: "mx-auto flex w-full justify-end pt-4 pl-4", style: chatAreaMaxWidth ? { maxWidth: `${chatAreaMaxWidth}px` } : undefined, children: jsx(RetrievedDocumentsButton, { sessionId: sessionId }) })), ((_c = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.data) === null || _c === void 0 ? void 0 : _c.disclaimer) && !compactMode && (jsx("div", { className: "mx-auto mt-1 w-full pb-1", style: chatAreaMaxWidth ? { maxWidth: `${chatAreaMaxWidth}px` } : undefined, children: jsx("p", { id: "chat-input-disclaimer", className: "text-center text-[0.625rem] text-gray-500 italic", children: (_d = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.data) === null || _d === void 0 ? void 0 : _d.disclaimer }) })), jsxs("form", { ref: containerRef, onSubmit: handleSubmit, className: cn('relative mx-auto mt-4 w-full pb-2', CSS_CLASS_NAMES.CHAT.TEXTAREA), style: chatAreaMaxWidth ? { maxWidth: `${chatAreaMaxWidth}px` } : undefined, children: [slashPicker.open && (jsx(SlashSkillPicker, { skills: slashPicker.filteredSkills, activeIndex: slashPicker.activeIndex, listboxId: slashPicker.listboxId, onSelect: slashPicker.selectSkill, onActiveIndexChange: slashPicker.setActiveIndex, isLoading: slashSkillsLoading })), jsxs("div", { className: "relative overflow-hidden rounded-2xl border border-gray-200 bg-[#fbfbfb] pb-3 shadow-xs", children: [jsx(FileAttachmentsList, { attachedFiles: attachedFiles, onRemoveFile: handleRemoveFile, onRetryFile: retryUpload }), fileAddedNotification && (jsxs("div", { className: "animate-in slide-in-from-bottom-5 absolute top-0 right-0 left-0 -mt-10 flex items-center gap-2 rounded-md bg-blue-50 p-2 text-xs text-blue-600 duration-300", children: [jsx(FileText, { className: "h-3 w-3" }), jsx("span", { className: "truncate", children: fileAddedNotification })] })), jsxs("div", { className: "grid", children: [jsx("label", { id: "chat-input-label", htmlFor: "chat-input-textarea", className: cn(persistentChatInputLabel
|
|
254705
255478
|
? 'block px-[18.5px] pt-3 text-xs font-medium text-gray-600'
|
|
254706
|
-
: 'sr-only'), children: t('chatInputForm.askAnything') }), jsx(AutoResizeTextarea, { id: "chat-input-textarea", "aria-labelledby": "chat-input-label", "aria-describedby": ((_e = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.data) === null || _e === void 0 ? void 0 : _e.disclaimer) ? 'chat-input-disclaimer' : undefined,
|
|
255479
|
+
: 'sr-only'), children: t('chatInputForm.askAnything') }), jsx(AutoResizeTextarea, { id: "chat-input-textarea", "aria-labelledby": "chat-input-label", "aria-describedby": ((_e = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.data) === null || _e === void 0 ? void 0 : _e.disclaimer) ? 'chat-input-disclaimer' : undefined, ...((effectiveSlashSkills.length > 0 || slashPicker.open) && {
|
|
255480
|
+
role: 'combobox',
|
|
255481
|
+
'aria-expanded': slashPicker.open,
|
|
255482
|
+
'aria-haspopup': 'listbox',
|
|
255483
|
+
'aria-controls': slashPicker.open && slashPicker.filteredSkills.length > 0
|
|
255484
|
+
? slashPicker.listboxId
|
|
255485
|
+
: undefined,
|
|
255486
|
+
'aria-activedescendant': slashPicker.activeOptionId,
|
|
255487
|
+
'aria-autocomplete': 'list',
|
|
255488
|
+
}), value: inputValue, onChange: handleInputChange, onSubmit: handleSubmit, onComposerKeyDown: slashPicker.handleKeyDown, sessionId: sessionId, isPreviewMode: isPreviewMode, textAreaRows: textAreaRows, placeholder: isChatDisabledByRbac ? t('chatInputForm.noChatPermission') : textAreaPlaceholder(), disabled: isChatDisabledByRbac || hasUploadingFiles, allowEmptySubmit: attachedFiles.length > 0, allowAnonymousAccess: isMentorViewableByAnyone || showingSharedChat || !!userIsVisiting, embedMode: embedMode }), jsxs("div", { className: "flex items-center gap-2 px-2", children: [visibleToLoggedInUsersOnly && !compactMode && (jsx(UploadMenu, { onFileInputTrigger: () => executeWithTrialCheck(triggerFileInput), disabled: isChatDisabledByRbac || !sessionId, mentorId: mentorId, tenantKey: tenantKey, isPublicRoute: isPublicRoute })), visibleToLoggedInUsersOnly && !compactMode && (jsx(InsideButtons, { containerWidth: containerWidth, activeOptions: activeTools, onOptionClick: updateSessionTools, deepResearch: deepResearch, artifactsEnabled: artifactsEnabled, disabled: isChatDisabledByRbac, onOpenPromptGallery: openPromptGallery, embedMode: embedMode, promptsIsEnabled: promptsIsEnabled, studyMode: studyMode, memoryEnabled: mentorSettings.data.memoryEnabled, mentorId: mentorId, tenantKey: tenantKey, username: username })), jsxs("div", { className: "ml-auto flex", children: [visibleToLoggedInUsersOnly && !compactMode && (jsx(ScreenSharingButton, { onClick: onScreenSharingClick, isScreenSharingModalOpen: isScreenSharingModalOpen, screenSharing: screenSharing, isPreviewMode: isPreviewMode, disabled: isChatDisabledByRbac })), visibleToLoggedInUsersOnly && !compactMode && (jsx(VoiceChatButton, { isPreviewMode: isPreviewMode, handleMicrophoneBtnClick: () => executeWithTrialCheck(handleMicrophoneBtnClick), processing: processing, recording: recording, disabled: isChatDisabledByRbac, mentorId: mentorId, tenantKey: tenantKey, isPublicRoute: isPublicRoute })), visibleToLoggedInUsersOnly && !compactMode && (jsx(VoiceCallButton, { isPreviewMode: isPreviewMode, onClick: () => executeWithTrialCheck(onPhoneCallClick), disabled: isChatDisabledByRbac, mentorId: mentorId, tenantKey: tenantKey, isPublicRoute: isPublicRoute })), isStreaming ? (jsx(StopStreamingButton, { ref: stopStreamingButtonRef, stopGenerating: stopGenerating })) : (jsx(SubmitMessageButton, { isPreviewMode: isPreviewMode, allowAnonymousAccess: isMentorViewableByAnyone, isUploading: hasUploadingFiles, disabled: isChatDisabledByRbac || !sessionId, isConnecting: isConnecting }))] })] })] }), jsx("input", { type: "file", ref: fileUploadInputRef, className: "hidden", onChange: handleFileInputChange, accept: fileUploadCapabilities.allSupportedTypes.length > 0
|
|
254707
255489
|
? fileUploadCapabilities.allSupportedTypes.join(',')
|
|
254708
255490
|
: MENTOR_CHAT_DOCUMENTS_EXTENSIONS.join(','), multiple: true, disabled: isChatDisabledByRbac || !sessionId })] }), visibleToLoggedInUsersOnly && !compactMode && (jsx("div", { className: "flex w-full justify-center", children: jsx(OutsideButtons, { activeOptions: activeTools, onOptionClick: updateSessionTools, setSessionTools: setSessionTools, onCrossClick: updateSessionTools, containerWidth: containerWidth, enableWebBrowsing: enableWebBrowsing, imageGeneration: imageGeneration, codeInterpreter: codeInterpreter, googleSlidesIsEnabled: googleSlidesIsEnabled, googleDocumentIsEnabled: googleDocumentIsEnabled, tenantKey: tenantKey, userId: username, disabled: isChatDisabledByRbac }) }))] }), isPromptGalleryOpen && (jsx(PromptGalleryModal$1, { isOpen: isPromptGalleryOpen, onClose: () => setIsPromptGalleryOpen(false), onSelectPrompt: handleSelectPrompt, mentorId: mentorId, tenantKey: tenantKey, userIsStudent: userIsStudent })), isFreeTrialModalOpen && FreeTrialDialog && (jsx(FreeTrialDialog, { isOpen: isFreeTrialModalOpen, onClose: closeFreeTrialModal }))] }));
|
|
254709
255491
|
}
|
|
@@ -257344,7 +258126,7 @@ function Account({ tenant, tenants = [], username, onInviteClick, email, mainPla
|
|
|
257344
258126
|
}, children: [jsxs("div", { className: "lg:hidden mb-6", children: [jsx("h3", { className: "text-lg font-medium text-gray-900 dark:text-gray-100 mb-2", children: (_d = (_c = TABS.find((t) => t.id === activeTab)) === null || _c === void 0 ? void 0 : _c.label) !== null && _d !== void 0 ? _d : activeTab }), jsxs("p", { className: "text-gray-600 dark:text-gray-400 text-sm", children: [activeTab === 'basic' && t('profileAccount.descBasic'), activeTab === 'social' && t('profileAccount.descSocial'), activeTab === 'security' && t('profileAccount.descSecurity'), activeTab === 'management' && t('profileAccount.descManagement'), activeTab === 'organization' && t('profileAccount.descOrganization'), activeTab === 'monetization' && t('profileAccount.descMonetization'), activeTab === 'datasets' && t('profileAccount.descBenchmarks'), activeTab === 'advanced' && t('profileAccount.descAdvanced')] })] }), activeTab === 'management' && hasManagementPermissions && (jsx(Admin, { authSpaUrl: authURL, onInviteClick: onInviteClick, tenant: tenant, currentSpa: currentSPA, hasUserTabPermission: hasUserTabPermission, hasGroupsTabPermission: hasGroupsTabPermission, hasPoliciesTabPermission: hasPoliciesTabPermission, hasRolesTabPermission: hasRolesTabPermission, hasTeamsTabPermission: hasTeamsTabPermission, hasInviteUserPermission: hasInviteUserPermission, hasCreateTeamPermission: hasCreateTeamPermission, onLoadGroupPermissions: onLoadGroupPermissions, hasAlertsTabPermission: hasAlertsTabPermission, rbacPermissions: rbacPermissions, enableRbac: enableRbac, showGradebookTab: showGradebookTab })), activeTab === 'organization' && (jsx(OrganizationTab, { platformKey: tenant, tenant: tenants.find((ten) => ten.key === tenant), onTenantUpdate: onTenantUpdate, setOrganizationLogoFromOutside: setOrganizationLogo, defaultSupportPhone: defaultSupportPhone, enableSupportPhone: enableSupportPhone })), activeTab === 'integrations' && (jsx(IntegrationsTab, { tenantKey: tenant, username: username })), activeTab === 'billing' && (jsx(BillingTab, { tenant: tenant, userActiveApp: userActiveApp, username: username, currentUserEmail: email, mainPlatformKey: mainPlatformKey })), activeTab === 'monetization' && (jsx(MonetizationTab, { platformKey: tenant, authURL: authURL })), activeTab === 'datasets' && showBenchmarks && (jsx(BenchmarksTab, { tenantKey: tenant, username: username })), activeTab === 'advanced' && (jsx(AdvancedTab, { platformKey: tenant, currentSPA: currentSPA, username: username, authURL: authURL, currentPlatformBaseDomain: currentPlatformBaseDomain }))] })] }), jsx(ToastProvider, {})] }));
|
|
257345
258127
|
}
|
|
257346
258128
|
|
|
257347
|
-
function UserProfileModal({ isOpen, onClose, params, email, mainPlatformKey, showMentorAIDisplayCheckbox = false, showLeaderboardDisplayCheckbox = false, showGradebookTab = false, showUsernameField = false, showPlatformName = false, useGravatarPicFallback = true, enableCatalogInvite = false, targetTab = 'basic', currentPlan = '', currentSPA = '', userActiveApp = null, authURL, tenants = [], onTenantUpdate, currentPlatformBaseDomain = '', rbacPermissions = {}, enableRbac = false, onLoadGroupPermissions, onTabChange, defaultSupportPhone = '', onBillingTabRequest, onAccountDeleted, enableMemoryTab = false, showBenchmarks = false, localLLMProps,
|
|
258129
|
+
function UserProfileModal({ isOpen, onClose, params, email, mainPlatformKey, showMentorAIDisplayCheckbox = false, showLeaderboardDisplayCheckbox = false, showGradebookTab = false, showUsernameField = false, showPlatformName = false, useGravatarPicFallback = true, enableCatalogInvite = false, targetTab = 'basic', currentPlan = '', currentSPA = '', userActiveApp = null, authURL, tenants = [], onTenantUpdate, currentPlatformBaseDomain = '', rbacPermissions = {}, enableRbac = false, onLoadGroupPermissions, onTabChange, defaultSupportPhone = '', onBillingTabRequest, onAccountDeleted, enableMemoryTab = false, showBenchmarks = false, localLLMProps, enableSupportPhone, }) {
|
|
257348
258130
|
const t = useT();
|
|
257349
258131
|
console.log('[UserProfileModal] localLLMProps received:', {
|
|
257350
258132
|
isAvailable: localLLMProps === null || localLLMProps === void 0 ? void 0 : localLLMProps.isAvailable,
|
|
@@ -257410,7 +258192,7 @@ function UserProfileModal({ isOpen, onClose, params, email, mainPlatformKey, sho
|
|
|
257410
258192
|
showPlatformName: showPlatformName,
|
|
257411
258193
|
useGravatarPicFallback: useGravatarPicFallback,
|
|
257412
258194
|
showGradebookTab: showGradebookTab,
|
|
257413
|
-
}, isAdmin: params.isAdmin, targetTab: targetTab, onClose: onClose, onAccountDeleted: onAccountDeleted, enableMemoryTab: enableMemoryTab, localLLMProps: localLLMProps
|
|
258195
|
+
}, isAdmin: params.isAdmin, targetTab: targetTab, onClose: onClose, onAccountDeleted: onAccountDeleted, enableMemoryTab: enableMemoryTab, localLLMProps: localLLMProps })), [
|
|
257414
258196
|
'organization',
|
|
257415
258197
|
'management',
|
|
257416
258198
|
'integrations',
|
|
@@ -257420,69 +258202,7 @@ function UserProfileModal({ isOpen, onClose, params, email, mainPlatformKey, sho
|
|
|
257420
258202
|
].includes(targetTab) && (jsxs(Fragment$1, { children: [jsx(Account, { onInviteClick: () => setIsInviteUserDialogOpen(true), tenant: params.tenantKey, tenants: tenants, username: getUserName$1(), email: email, mainPlatformKey: mainPlatformKey, showUsernameField: showUsernameField, showPlatformName: showPlatformName, useGravatarPicFallback: useGravatarPicFallback, onClose: onClose, isAdmin: params.isAdmin, targetTab: targetTab, currentPlan: currentPlan, currentSPA: currentSPA, userActiveApp: userActiveApp, authURL: authURL, onTenantUpdate: onTenantUpdate, currentPlatformBaseDomain: currentPlatformBaseDomain, rbacPermissions: rbacPermissions, enableRbac: enableRbac, onLoadGroupPermissions: onLoadGroupPermissions, onTabChange: onTabChange, defaultSupportPhone: defaultSupportPhone, showBenchmarks: showBenchmarks, enableSupportPhone: enableSupportPhone, showGradebookTab: showGradebookTab }), isInviteUserDialogOpen && (jsx(InviteUserDialog, { tenant: params.tenantKey, onClose: () => setIsInviteUserDialogOpen(false), isOpen: isInviteUserDialogOpen, enableCatalogInvite: enableCatalogInvite, hasManageUsersPermission: hasManageUsersPermission })), isInvitedUsersDialogOpen && (jsx(InvitedUsersDialog, { onClose: () => setIsInvitedUsersDialogOpen(false), tenant: params.tenantKey }))] }))] }) }) }));
|
|
257421
258203
|
}
|
|
257422
258204
|
|
|
257423
|
-
const
|
|
257424
|
-
/**
|
|
257425
|
-
* A simplified useLocalStorage hook for persisting state to localStorage
|
|
257426
|
-
* with SSR safety.
|
|
257427
|
-
*/
|
|
257428
|
-
function useLocalStorage(key, initialValue) {
|
|
257429
|
-
// Get the initial value
|
|
257430
|
-
const getInitialValue = useCallback(() => {
|
|
257431
|
-
const initial = initialValue instanceof Function ? initialValue() : initialValue;
|
|
257432
|
-
if (IS_SERVER) {
|
|
257433
|
-
return initial;
|
|
257434
|
-
}
|
|
257435
|
-
try {
|
|
257436
|
-
const item = window.localStorage.getItem(key);
|
|
257437
|
-
if (item === null) {
|
|
257438
|
-
return initial;
|
|
257439
|
-
}
|
|
257440
|
-
return JSON.parse(item);
|
|
257441
|
-
}
|
|
257442
|
-
catch (error) {
|
|
257443
|
-
console.warn(`Error reading localStorage key "${key}":`, error);
|
|
257444
|
-
return initial;
|
|
257445
|
-
}
|
|
257446
|
-
}, [key, initialValue]);
|
|
257447
|
-
const [storedValue, setStoredValue] = useState(getInitialValue);
|
|
257448
|
-
// Update stored value when key changes
|
|
257449
|
-
useEffect(() => {
|
|
257450
|
-
setStoredValue(getInitialValue());
|
|
257451
|
-
}, [key, getInitialValue]);
|
|
257452
|
-
// Persist to localStorage
|
|
257453
|
-
const setValue = useCallback((value) => {
|
|
257454
|
-
if (IS_SERVER) {
|
|
257455
|
-
console.warn(`Tried setting localStorage key "${key}" even though environment is not a client`);
|
|
257456
|
-
return;
|
|
257457
|
-
}
|
|
257458
|
-
try {
|
|
257459
|
-
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
|
257460
|
-
setStoredValue(valueToStore);
|
|
257461
|
-
window.localStorage.setItem(key, JSON.stringify(valueToStore));
|
|
257462
|
-
}
|
|
257463
|
-
catch (error) {
|
|
257464
|
-
console.warn(`Error setting localStorage key "${key}":`, error);
|
|
257465
|
-
}
|
|
257466
|
-
}, [key, storedValue]);
|
|
257467
|
-
// Remove from localStorage
|
|
257468
|
-
const removeValue = useCallback(() => {
|
|
257469
|
-
if (IS_SERVER) {
|
|
257470
|
-
console.warn(`Tried removing localStorage key "${key}" even though environment is not a client`);
|
|
257471
|
-
return;
|
|
257472
|
-
}
|
|
257473
|
-
try {
|
|
257474
|
-
const initial = initialValue instanceof Function ? initialValue() : initialValue;
|
|
257475
|
-
window.localStorage.removeItem(key);
|
|
257476
|
-
setStoredValue(initial);
|
|
257477
|
-
}
|
|
257478
|
-
catch (error) {
|
|
257479
|
-
console.warn(`Error removing localStorage key "${key}":`, error);
|
|
257480
|
-
}
|
|
257481
|
-
}, [key, initialValue]);
|
|
257482
|
-
return [storedValue, setValue, removeValue];
|
|
257483
|
-
}
|
|
257484
|
-
|
|
257485
|
-
const LOCAL_STORAGE_KEY$1 = 'model_download_state';
|
|
258205
|
+
const LOCAL_STORAGE_KEY = 'model_download_state';
|
|
257486
258206
|
const FIRST_LAUNCH_DISMISSED_KEY = 'model_download_prompt_dismissed';
|
|
257487
258207
|
// Manager/download status is authoritative from Tauri, never the persisted
|
|
257488
258208
|
// snapshot. This flips true the first time any hook instance mounts in a page
|
|
@@ -257502,7 +258222,7 @@ let didResetPersistedState = false;
|
|
|
257502
258222
|
*/
|
|
257503
258223
|
function useModelDownload() {
|
|
257504
258224
|
const { isAvailable, invoke, listen } = useTauri();
|
|
257505
|
-
const [state, setState] = useLocalStorage(LOCAL_STORAGE_KEY
|
|
258225
|
+
const [state, setState] = useLocalStorage(LOCAL_STORAGE_KEY, initialModelDownloadState);
|
|
257506
258226
|
const [ollamaStatus, setOllamaStatus] = useState(null);
|
|
257507
258227
|
const [systemMemory, setSystemMemory] = useState(null);
|
|
257508
258228
|
const [isFirstLaunchDismissed, setIsFirstLaunchDismissed] = useLocalStorage(FIRST_LAUNCH_DISMISSED_KEY, false);
|
|
@@ -257930,224 +258650,6 @@ function useModelDownload() {
|
|
|
257930
258650
|
};
|
|
257931
258651
|
}
|
|
257932
258652
|
|
|
257933
|
-
const LOCAL_STORAGE_KEY = 'ghost_os_install_state';
|
|
257934
|
-
/**
|
|
257935
|
-
* Manage installing & setting up GhostOS (https://github.com/ghostwright/ghost-os)
|
|
257936
|
-
* via the Tauri host. This is the self-contained backing hook for the System
|
|
257937
|
-
* Control card and deliberately mirrors `useModelDownload`:
|
|
257938
|
-
*
|
|
257939
|
-
* - checks GhostOS install/run status through the host
|
|
257940
|
-
* - installs/sets up GhostOS with real-time progress + logs
|
|
257941
|
-
* - persists state across app restarts
|
|
257942
|
-
*
|
|
257943
|
-
* Outside the desktop (Tauri) app every action is a no-op and `isAvailable` is
|
|
257944
|
-
* false, so the card hides itself.
|
|
257945
|
-
*/
|
|
257946
|
-
function useGhostOs() {
|
|
257947
|
-
const { isAvailable, invoke, listen } = useTauri();
|
|
257948
|
-
const [state, setState] = useLocalStorage(LOCAL_STORAGE_KEY, initialGhostOsInstallState);
|
|
257949
|
-
const [status, setStatus] = useState(null);
|
|
257950
|
-
// macOS Accessibility permission, which GhostOS needs to control the device.
|
|
257951
|
-
// null = unknown/not-yet-checked or unsupported (non-macOS / plugin absent).
|
|
257952
|
-
const [accessibilityPermission, setAccessibilityPermission] = useState(null);
|
|
257953
|
-
const unlistenRefs = useRef([]);
|
|
257954
|
-
const hasCheckedStatus = useRef(false);
|
|
257955
|
-
/**
|
|
257956
|
-
* Refresh the macOS Accessibility permission via tauri-plugin-macos-permissions.
|
|
257957
|
-
* Independent of the GhostOS status check so a missing host command for one
|
|
257958
|
-
* doesn't suppress the other. Stays null where unsupported.
|
|
257959
|
-
*/
|
|
257960
|
-
const refreshAccessibilityPermission = useCallback(async () => {
|
|
257961
|
-
if (!isAvailable)
|
|
257962
|
-
return;
|
|
257963
|
-
try {
|
|
257964
|
-
const granted = await invoke(MACOS_PERMISSIONS_COMMANDS.CHECK_ACCESSIBILITY);
|
|
257965
|
-
setAccessibilityPermission(granted);
|
|
257966
|
-
}
|
|
257967
|
-
catch (error) {
|
|
257968
|
-
// Plugin not registered or non-macOS host — leave permission unknown.
|
|
257969
|
-
console.warn('[useGhostOs] Accessibility permission check unavailable:', error);
|
|
257970
|
-
setAccessibilityPermission(null);
|
|
257971
|
-
}
|
|
257972
|
-
}, [isAvailable, invoke]);
|
|
257973
|
-
/**
|
|
257974
|
-
* Open the Accessibility pane / prompt so the user can grant permission, then
|
|
257975
|
-
* re-check (the grant happens in System Settings, so we refresh after).
|
|
257976
|
-
*/
|
|
257977
|
-
const requestAccessibilityPermission = useCallback(async () => {
|
|
257978
|
-
if (!isAvailable)
|
|
257979
|
-
return;
|
|
257980
|
-
try {
|
|
257981
|
-
await invoke(MACOS_PERMISSIONS_COMMANDS.REQUEST_ACCESSIBILITY);
|
|
257982
|
-
}
|
|
257983
|
-
catch (error) {
|
|
257984
|
-
console.error('[useGhostOs] Failed to request accessibility permission:', error);
|
|
257985
|
-
}
|
|
257986
|
-
await refreshAccessibilityPermission();
|
|
257987
|
-
}, [isAvailable, invoke, refreshAccessibilityPermission]);
|
|
257988
|
-
const addLog = useCallback((log) => {
|
|
257989
|
-
setState((prev) => ({
|
|
257990
|
-
...prev,
|
|
257991
|
-
logs: [...prev.logs.slice(-99), log],
|
|
257992
|
-
lastUpdated: new Date().toISOString(),
|
|
257993
|
-
}));
|
|
257994
|
-
}, [setState]);
|
|
257995
|
-
/**
|
|
257996
|
-
* Query GhostOS status from the host.
|
|
257997
|
-
*/
|
|
257998
|
-
const checkStatus = useCallback(async () => {
|
|
257999
|
-
if (!isAvailable)
|
|
258000
|
-
return;
|
|
258001
|
-
// Refresh the accessibility permission alongside install status (independent).
|
|
258002
|
-
refreshAccessibilityPermission();
|
|
258003
|
-
try {
|
|
258004
|
-
setState((prev) => ({ ...prev, status: 'checking' }));
|
|
258005
|
-
const result = await invoke(GHOST_OS_TAURI_COMMANDS.CHECK_GHOST_OS_STATUS);
|
|
258006
|
-
setStatus(result);
|
|
258007
|
-
setState((prev) => ({
|
|
258008
|
-
...prev,
|
|
258009
|
-
status: result.installed ? 'completed' : 'idle',
|
|
258010
|
-
progress: result.installed ? 100 : prev.progress,
|
|
258011
|
-
lastUpdated: new Date().toISOString(),
|
|
258012
|
-
}));
|
|
258013
|
-
}
|
|
258014
|
-
catch (error) {
|
|
258015
|
-
console.error('[useGhostOs] Failed to check status:', error);
|
|
258016
|
-
setState((prev) => ({ ...prev, status: 'idle' }));
|
|
258017
|
-
}
|
|
258018
|
-
}, [isAvailable, invoke, setState, refreshAccessibilityPermission]);
|
|
258019
|
-
/**
|
|
258020
|
-
* Install and set up GhostOS. The host clones the repo + runs setup and emits
|
|
258021
|
-
* progress/log/status events along the way.
|
|
258022
|
-
*/
|
|
258023
|
-
const install = useCallback(async () => {
|
|
258024
|
-
if (!isAvailable)
|
|
258025
|
-
return;
|
|
258026
|
-
try {
|
|
258027
|
-
setState((prev) => ({
|
|
258028
|
-
...prev,
|
|
258029
|
-
status: 'installing',
|
|
258030
|
-
progress: 0,
|
|
258031
|
-
message: 'Setting up your assistant…',
|
|
258032
|
-
error: undefined,
|
|
258033
|
-
logs: [],
|
|
258034
|
-
}));
|
|
258035
|
-
addLog({
|
|
258036
|
-
timestamp: new Date().toISOString(),
|
|
258037
|
-
level: 'info',
|
|
258038
|
-
message: 'Starting setup…',
|
|
258039
|
-
});
|
|
258040
|
-
const result = await invoke(GHOST_OS_TAURI_COMMANDS.INSTALL_GHOST_OS);
|
|
258041
|
-
addLog({
|
|
258042
|
-
timestamp: new Date().toISOString(),
|
|
258043
|
-
level: 'info',
|
|
258044
|
-
message: typeof result === 'string' && result ? result : 'Setup complete',
|
|
258045
|
-
});
|
|
258046
|
-
setState((prev) => ({
|
|
258047
|
-
...prev,
|
|
258048
|
-
status: 'completed',
|
|
258049
|
-
progress: 100,
|
|
258050
|
-
message: 'Your assistant is ready',
|
|
258051
|
-
lastUpdated: new Date().toISOString(),
|
|
258052
|
-
}));
|
|
258053
|
-
await checkStatus();
|
|
258054
|
-
}
|
|
258055
|
-
catch (error) {
|
|
258056
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
258057
|
-
setState((prev) => ({
|
|
258058
|
-
...prev,
|
|
258059
|
-
status: 'error',
|
|
258060
|
-
error: message,
|
|
258061
|
-
message: 'Setup didn’t finish',
|
|
258062
|
-
lastUpdated: new Date().toISOString(),
|
|
258063
|
-
}));
|
|
258064
|
-
addLog({
|
|
258065
|
-
timestamp: new Date().toISOString(),
|
|
258066
|
-
level: 'error',
|
|
258067
|
-
message: `Install failed: ${message}`,
|
|
258068
|
-
});
|
|
258069
|
-
}
|
|
258070
|
-
}, [isAvailable, invoke, addLog, checkStatus, setState]);
|
|
258071
|
-
/**
|
|
258072
|
-
* Stop the running GhostOS manager.
|
|
258073
|
-
*/
|
|
258074
|
-
const stop = useCallback(async () => {
|
|
258075
|
-
if (!isAvailable)
|
|
258076
|
-
return;
|
|
258077
|
-
try {
|
|
258078
|
-
await invoke(GHOST_OS_TAURI_COMMANDS.STOP_GHOST_OS);
|
|
258079
|
-
await checkStatus();
|
|
258080
|
-
}
|
|
258081
|
-
catch (error) {
|
|
258082
|
-
console.error('[useGhostOs] Failed to stop GhostOS:', error);
|
|
258083
|
-
}
|
|
258084
|
-
}, [isAvailable, invoke, checkStatus]);
|
|
258085
|
-
/**
|
|
258086
|
-
* Reset the install state (for retrying after an error).
|
|
258087
|
-
*/
|
|
258088
|
-
const resetState = useCallback(() => {
|
|
258089
|
-
setState(initialGhostOsInstallState);
|
|
258090
|
-
}, [setState]);
|
|
258091
|
-
// Wire up host event listeners (progress / logs / status).
|
|
258092
|
-
useEffect(() => {
|
|
258093
|
-
if (!isAvailable)
|
|
258094
|
-
return;
|
|
258095
|
-
const setupListeners = async () => {
|
|
258096
|
-
try {
|
|
258097
|
-
const unlistenProgress = await listen(GHOST_OS_TAURI_EVENTS.INSTALL_PROGRESS, (payload) => {
|
|
258098
|
-
const nextStatus = payload.status === 'completed'
|
|
258099
|
-
? 'completed'
|
|
258100
|
-
: payload.status === 'cancelled'
|
|
258101
|
-
? 'cancelled'
|
|
258102
|
-
: payload.status === 'error'
|
|
258103
|
-
? 'error'
|
|
258104
|
-
: 'installing';
|
|
258105
|
-
setState((prev) => ({
|
|
258106
|
-
...prev,
|
|
258107
|
-
status: nextStatus,
|
|
258108
|
-
progress: payload.percentage,
|
|
258109
|
-
message: payload.message,
|
|
258110
|
-
lastUpdated: new Date().toISOString(),
|
|
258111
|
-
}));
|
|
258112
|
-
});
|
|
258113
|
-
unlistenRefs.current.push(unlistenProgress);
|
|
258114
|
-
const unlistenLogs = await listen(GHOST_OS_TAURI_EVENTS.INSTALLATION_LOG, addLog);
|
|
258115
|
-
unlistenRefs.current.push(unlistenLogs);
|
|
258116
|
-
const unlistenStatus = await listen(GHOST_OS_TAURI_EVENTS.STATUS, setStatus);
|
|
258117
|
-
unlistenRefs.current.push(unlistenStatus);
|
|
258118
|
-
}
|
|
258119
|
-
catch (error) {
|
|
258120
|
-
console.error('[useGhostOs] Failed to setup event listeners:', error);
|
|
258121
|
-
}
|
|
258122
|
-
};
|
|
258123
|
-
setupListeners();
|
|
258124
|
-
return () => {
|
|
258125
|
-
unlistenRefs.current.forEach((unlisten) => unlisten());
|
|
258126
|
-
unlistenRefs.current = [];
|
|
258127
|
-
};
|
|
258128
|
-
}, [isAvailable, listen, setState, addLog]);
|
|
258129
|
-
// Check status once on mount (in the desktop app).
|
|
258130
|
-
useEffect(() => {
|
|
258131
|
-
if (!isAvailable || hasCheckedStatus.current)
|
|
258132
|
-
return;
|
|
258133
|
-
hasCheckedStatus.current = true;
|
|
258134
|
-
checkStatus();
|
|
258135
|
-
}, [isAvailable, checkStatus]);
|
|
258136
|
-
// Only expose the feature as available inside the desktop (Tauri) app.
|
|
258137
|
-
const finalIsAvailable = isAvailable && isTauriApp$1();
|
|
258138
|
-
return {
|
|
258139
|
-
isAvailable: finalIsAvailable,
|
|
258140
|
-
state,
|
|
258141
|
-
status,
|
|
258142
|
-
accessibilityPermission,
|
|
258143
|
-
install,
|
|
258144
|
-
stop,
|
|
258145
|
-
checkStatus,
|
|
258146
|
-
resetState,
|
|
258147
|
-
requestAccessibilityPermission,
|
|
258148
|
-
};
|
|
258149
|
-
}
|
|
258150
|
-
|
|
258151
258653
|
function UserProfileDropdown({ email, mainPlatformKey,
|
|
258152
258654
|
// User data
|
|
258153
258655
|
username, userIsAdmin = false, userIsStudent = false, userIsVisiting = false,
|
|
@@ -258171,11 +258673,9 @@ metadata, metadataLoaded = false,
|
|
|
258171
258673
|
currentSPA = '', showMentorAIDisplayCheckbox = false, showLeaderboardDisplayCheckbox = false, showGradebookTab = false, showUsernameField = false, showPlatformName = false, enableCatalogInvite = false, authURL, onTenantUpdate, currentPlatformBaseDomain = '', rbacPermissions = {}, enableRbac = false, onLoadGroupPermissions, defaultSupportPhone = '', enableSupportPhone,
|
|
258172
258674
|
// Local LLM props
|
|
258173
258675
|
localLLMProps,
|
|
258174
|
-
// System Control props
|
|
258175
|
-
systemControlProps,
|
|
258176
258676
|
// Controlled modal state
|
|
258177
258677
|
isModalOpen, onModalOpenChange, defaultActiveTab, onAccountDeleted, enableMemoryTab, showBenchmarks = false, }) {
|
|
258178
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k
|
|
258678
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
258179
258679
|
const t = useT();
|
|
258180
258680
|
// Use hooks to fetch user metadata
|
|
258181
258681
|
const { data: userMetadata } = useGetUserMetadataQuery({
|
|
@@ -258203,17 +258703,6 @@ isModalOpen, onModalOpenChange, defaultActiveTab, onAccountDeleted, enableMemory
|
|
|
258203
258703
|
const selectedFoundryModel = localLLMProps === null || localLLMProps === void 0 ? void 0 : localLLMProps.selectedFoundryModel;
|
|
258204
258704
|
const foundryStatus = localLLMProps === null || localLLMProps === void 0 ? void 0 : localLLMProps.foundryStatus;
|
|
258205
258705
|
const onSelectFoundryModel = localLLMProps === null || localLLMProps === void 0 ? void 0 : localLLMProps.onSelectFoundryModel;
|
|
258206
|
-
// System Control (GhostOS) state from props (if provided) or from hook (fallback)
|
|
258207
|
-
const ghostOsData = useGhostOs();
|
|
258208
|
-
const isSystemControlAvailable = (_l = systemControlProps === null || systemControlProps === void 0 ? void 0 : systemControlProps.isAvailable) !== null && _l !== void 0 ? _l : ghostOsData.isAvailable;
|
|
258209
|
-
const systemControlState = (_m = systemControlProps === null || systemControlProps === void 0 ? void 0 : systemControlProps.state) !== null && _m !== void 0 ? _m : ghostOsData.state;
|
|
258210
|
-
const systemControlStatus = (_o = systemControlProps === null || systemControlProps === void 0 ? void 0 : systemControlProps.status) !== null && _o !== void 0 ? _o : ghostOsData.status;
|
|
258211
|
-
const accessibilityPermission = (_p = systemControlProps === null || systemControlProps === void 0 ? void 0 : systemControlProps.accessibilityPermission) !== null && _p !== void 0 ? _p : ghostOsData.accessibilityPermission;
|
|
258212
|
-
const installGhostOs = (_q = systemControlProps === null || systemControlProps === void 0 ? void 0 : systemControlProps.onInstall) !== null && _q !== void 0 ? _q : ghostOsData.install;
|
|
258213
|
-
const stopGhostOs = (_r = systemControlProps === null || systemControlProps === void 0 ? void 0 : systemControlProps.onStop) !== null && _r !== void 0 ? _r : ghostOsData.stop;
|
|
258214
|
-
const checkGhostOsStatus = (_s = systemControlProps === null || systemControlProps === void 0 ? void 0 : systemControlProps.onCheckStatus) !== null && _s !== void 0 ? _s : ghostOsData.checkStatus;
|
|
258215
|
-
const resetGhostOsState = (_t = systemControlProps === null || systemControlProps === void 0 ? void 0 : systemControlProps.onResetState) !== null && _t !== void 0 ? _t : ghostOsData.resetState;
|
|
258216
|
-
const requestAccessibilityPermission = (_u = systemControlProps === null || systemControlProps === void 0 ? void 0 : systemControlProps.onRequestAccessibilityPermission) !== null && _u !== void 0 ? _u : ghostOsData.requestAccessibilityPermission;
|
|
258217
258706
|
// Support controlled modal state
|
|
258218
258707
|
const [internalIsUserProfileOpen, setInternalIsUserProfileOpen] = useState(false);
|
|
258219
258708
|
const isUserProfileOpen = isModalOpen !== null && isModalOpen !== void 0 ? isModalOpen : internalIsUserProfileOpen;
|
|
@@ -258390,23 +258879,6 @@ isModalOpen, onModalOpenChange, defaultActiveTab, onAccountDeleted, enableMemory
|
|
|
258390
258879
|
onResetState: resetState,
|
|
258391
258880
|
onSelectFoundryModel,
|
|
258392
258881
|
},
|
|
258393
|
-
systemControlProps: {
|
|
258394
|
-
isAvailable: isSystemControlAvailable,
|
|
258395
|
-
state: systemControlState,
|
|
258396
|
-
status: systemControlStatus,
|
|
258397
|
-
requiredSizeGb: systemControlProps === null || systemControlProps === void 0 ? void 0 : systemControlProps.requiredSizeGb,
|
|
258398
|
-
// Local-model status/memory + downloader, so the "Upgrade" action can
|
|
258399
|
-
// check what's installed, keep the RAM/VRAM check, and pull a model.
|
|
258400
|
-
ollamaStatus,
|
|
258401
|
-
systemMemory,
|
|
258402
|
-
accessibilityPermission,
|
|
258403
|
-
onInstall: installGhostOs,
|
|
258404
|
-
onStop: stopGhostOs,
|
|
258405
|
-
onCheckStatus: checkGhostOsStatus,
|
|
258406
|
-
onResetState: resetGhostOsState,
|
|
258407
|
-
onRequestAccessibilityPermission: requestAccessibilityPermission,
|
|
258408
|
-
onDownloadModel: startDownload,
|
|
258409
|
-
},
|
|
258410
258882
|
onAccountDeleted,
|
|
258411
258883
|
enableMemoryTab,
|
|
258412
258884
|
showBenchmarks,
|
|
@@ -267188,7 +267660,9 @@ function PromptCard$1({ label, placeholder, value, disabled, renderContent, onEd
|
|
|
267188
267660
|
|
|
267189
267661
|
const AGENT_SCREENSHARE_TAB_LABELS = {
|
|
267190
267662
|
header: {
|
|
267191
|
-
|
|
267663
|
+
// Title is deliberately just "Screen" — the description below carries the
|
|
267664
|
+
// screen-sharing wording.
|
|
267665
|
+
title: 'Screen',
|
|
267192
267666
|
description: 'How your agent behaves when a user shares their screen during a voice call.',
|
|
267193
267667
|
},
|
|
267194
267668
|
capability: {
|
|
@@ -267408,6 +267882,86 @@ function AgentScreenShareTab({ labels: labelsOverride, renderPromptContent, tena
|
|
|
267408
267882
|
} }) }))] })) })] }));
|
|
267409
267883
|
}
|
|
267410
267884
|
|
|
267885
|
+
const AGENT_SKILLS_TAB_LABELS = {
|
|
267886
|
+
header: {
|
|
267887
|
+
title: 'Skills',
|
|
267888
|
+
description: 'Reusable playbooks you can attach to this agent — each one is a set of instructions for a job. In chat, type / to use one.',
|
|
267889
|
+
},
|
|
267890
|
+
notBaseAgent: 'Skills are only available to Base Agents.',
|
|
267891
|
+
loading: 'Loading...',
|
|
267892
|
+
};
|
|
267893
|
+
function buildSkillsTabLabels(t) {
|
|
267894
|
+
return {
|
|
267895
|
+
header: {
|
|
267896
|
+
title: t('skillsTabLabels.header.title'),
|
|
267897
|
+
description: t('skillsTabLabels.header.description'),
|
|
267898
|
+
},
|
|
267899
|
+
notBaseAgent: t('skillsTabLabels.notBaseAgent'),
|
|
267900
|
+
loading: t('skillsTabLabels.loading'),
|
|
267901
|
+
};
|
|
267902
|
+
}
|
|
267903
|
+
function resolveSkillsTabLabels(override, t) {
|
|
267904
|
+
const base = t ? buildSkillsTabLabels(t) : AGENT_SKILLS_TAB_LABELS;
|
|
267905
|
+
if (!override)
|
|
267906
|
+
return base;
|
|
267907
|
+
return deepMerge(base, override);
|
|
267908
|
+
}
|
|
267909
|
+
|
|
267910
|
+
/**
|
|
267911
|
+
* Best-effort slug extraction from the `template_mentor` field, whose shape
|
|
267912
|
+
* is untyped on the settings serializer (string slug or nested object).
|
|
267913
|
+
*/
|
|
267914
|
+
function templateMentorSlug(template) {
|
|
267915
|
+
if (typeof template === 'string')
|
|
267916
|
+
return template;
|
|
267917
|
+
if (template && typeof template === 'object') {
|
|
267918
|
+
const record = template;
|
|
267919
|
+
for (const key of ['slug', 'mentor_slug', 'template_slug']) {
|
|
267920
|
+
if (typeof record[key] === 'string')
|
|
267921
|
+
return record[key];
|
|
267922
|
+
}
|
|
267923
|
+
}
|
|
267924
|
+
return undefined;
|
|
267925
|
+
}
|
|
267926
|
+
/**
|
|
267927
|
+
* The Skills section of the agent configuration modal. Resolves the agent's
|
|
267928
|
+
* UUID from mentor settings and renders the AgentSkills manager (effective
|
|
267929
|
+
* skills + attachable catalog). Skills only apply to Base Agents — when the
|
|
267930
|
+
* settings identify another agent type, an informational note renders
|
|
267931
|
+
* instead. Hosts should also hide the tab for non-Base-Agents when they can.
|
|
267932
|
+
*/
|
|
267933
|
+
function AgentSkillsTab({ labels: labelsOverride, tenantKey: tenantKeyProp, mentorId: mentorIdProp, username: usernameProp, userIsStudent: userIsStudentProp, }) {
|
|
267934
|
+
var _a, _b, _c, _d, _e;
|
|
267935
|
+
const t = useT();
|
|
267936
|
+
const labels = React__default.useMemo(() => resolveSkillsTabLabels(labelsOverride, t), [labelsOverride, t]);
|
|
267937
|
+
const ctx = useAgentSettingsOptional();
|
|
267938
|
+
const tenantKey = (_a = tenantKeyProp !== null && tenantKeyProp !== void 0 ? tenantKeyProp : ctx === null || ctx === void 0 ? void 0 : ctx.tenantKey) !== null && _a !== void 0 ? _a : '';
|
|
267939
|
+
const mentorId = (_b = mentorIdProp !== null && mentorIdProp !== void 0 ? mentorIdProp : ctx === null || ctx === void 0 ? void 0 : ctx.mentorId) !== null && _b !== void 0 ? _b : '';
|
|
267940
|
+
const username = (_c = usernameProp !== null && usernameProp !== void 0 ? usernameProp : ctx === null || ctx === void 0 ? void 0 : ctx.username) !== null && _c !== void 0 ? _c : '';
|
|
267941
|
+
// Agent Skills are admin-only: render nothing for learners even if a host
|
|
267942
|
+
// registers the tab or deep-links to it. Prop overrides context.
|
|
267943
|
+
const userIsStudent = (_d = userIsStudentProp !== null && userIsStudentProp !== void 0 ? userIsStudentProp : ctx === null || ctx === void 0 ? void 0 : ctx.userIsStudent) !== null && _d !== void 0 ? _d : false;
|
|
267944
|
+
const { data: mentorSettings, isLoading: isSettingsLoading } = useGetMentorSettingsQuery({
|
|
267945
|
+
mentor: mentorId,
|
|
267946
|
+
org: tenantKey,
|
|
267947
|
+
}, { skip: !username || !mentorId || !tenantKey || userIsStudent });
|
|
267948
|
+
const settings = mentorSettings;
|
|
267949
|
+
const mentorUniqueId = (_e = settings === null || settings === void 0 ? void 0 : settings.mentor_unique_id) !== null && _e !== void 0 ? _e : '';
|
|
267950
|
+
const templateSlug = templateMentorSlug(settings === null || settings === void 0 ? void 0 : settings.template_mentor);
|
|
267951
|
+
// Only block when the template positively identifies a non-Base-Agent type;
|
|
267952
|
+
// with no template evidence (custom mentors carry their own slug), render
|
|
267953
|
+
// the manager and let the backend enforce.
|
|
267954
|
+
const knownNotBaseAgent = !!settings &&
|
|
267955
|
+
templateSlug !== undefined &&
|
|
267956
|
+
!isBaseAgentMentor({ mentorSlug: settings.mentor_slug, templateMentorSlug: templateSlug });
|
|
267957
|
+
if (userIsStudent)
|
|
267958
|
+
return null;
|
|
267959
|
+
return (jsxs(Fragment$1, { children: [jsx("div", { className: "hidden h-[73px] flex-shrink-0 items-center border-b border-gray-200 bg-white p-4 lg:block", children: jsxs("div", { children: [jsx("h3", { className: "mb-1 text-base font-medium text-gray-900", children: labels.header.title }), jsx("p", { className: "text-xs text-gray-700", children: labels.header.description })] }) }), jsx("div", { className: "flex-1 space-y-4 p-3", style: {
|
|
267960
|
+
overflowY: 'auto',
|
|
267961
|
+
overflowX: 'hidden',
|
|
267962
|
+
}, children: isSettingsLoading || !mentorUniqueId ? (jsxs("div", { className: "flex items-center gap-2 p-4", role: "status", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin text-blue-500" }), jsx("span", { className: "text-sm text-gray-500", children: labels.loading })] })) : knownNotBaseAgent ? (jsx("div", { className: "flex items-center justify-center rounded-lg border p-6", children: jsx("p", { className: "text-sm text-gray-500", children: labels.notBaseAgent }) })) : (jsx(AgentSkills, { platformKey: tenantKey, mentorUniqueId: mentorUniqueId })) })] }));
|
|
267963
|
+
}
|
|
267964
|
+
|
|
267411
267965
|
const AGENT_GRADER_TAB_LABELS = {
|
|
267412
267966
|
header: {
|
|
267413
267967
|
title: 'Grader',
|
|
@@ -269491,7 +270045,7 @@ function AgentLinksSection({ identity, labels, }) {
|
|
|
269491
270045
|
event.stopPropagation();
|
|
269492
270046
|
setEditingLink(link);
|
|
269493
270047
|
}, children: jsx(Pencil, { className: "h-4 w-4" }) }) })] }, link.id));
|
|
269494
|
-
}) })] }) }), isFetching && (jsx("p", { className: "px-3 py-2 text-xs text-gray-400", children: labels.common.refreshing }))] })), jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: busy
|
|
270048
|
+
}) })] }) }), isFetching && (jsx("p", { className: "px-3 py-2 text-xs text-gray-400", children: labels.common.refreshing }))] })), jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: busy }), showCreate && (jsx(AgentLinkModal, { isOpen: showCreate, onClose: () => setShowCreate(false), platformKey: platformKey, mentorId: mentorId, mentorUniqueId: mentorUniqueId, username: username, isLtiAccessible: isLtiAccessible, labels: labels })), editingLink && (jsx(AgentLinkModal, { isOpen: Boolean(editingLink), onClose: () => setEditingLink(null), platformKey: platformKey, mentorId: mentorId, mentorUniqueId: mentorUniqueId, username: username, isLtiAccessible: isLtiAccessible, link: editingLink, labels: labels }))] }));
|
|
269495
270049
|
}
|
|
269496
270050
|
|
|
269497
270051
|
function KeyCreateModal({ isOpen, onClose, platformKey, labels }) {
|
|
@@ -269588,7 +270142,7 @@ function KeysSection({ identity, labels }) {
|
|
|
269588
270142
|
const keys = React__default.useMemo(() => toArray(keysData), [keysData]);
|
|
269589
270143
|
const totalPages = getTotalPages(keysData);
|
|
269590
270144
|
const busy = !isReady || isLoading;
|
|
269591
|
-
return (jsxs("div", { className: "space-y-4", "data-testid": "lti-keys-section", children: [jsxs("div", { className: "flex flex-col items-start justify-between gap-3 sm:flex-row sm:items-center", children: [jsx("p", { className: "text-xs text-gray-600", children: labels.keys.description }), jsxs(Button$1, { onClick: () => setShowCreate(true), size: "sm", "data-testid": "lti-key-create-button", className: "cursor-pointer whitespace-nowrap bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: [jsx(Plus, { className: "h-4 w-4" }), labels.keys.createButton] })] }), busy ? (jsx("div", { className: "flex w-full items-center justify-center py-10", children: jsx(Spinner, {}) })) : keys.length === 0 ? (jsxs("div", { className: "flex flex-col items-center justify-center gap-3 rounded-md border border-dashed border-gray-200 py-12 text-center", "data-testid": "lti-keys-empty", children: [jsx(KeyRound, { className: "h-8 w-8 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm text-[#646464]", children: labels.keys.empty })] })) : (jsxs("div", { className: "overflow-hidden rounded-md border", children: [jsx("div", { className: "overflow-x-auto", children: jsxs(Table$1, { className: "min-w-full", children: [jsx(TableHeader$1, { children: jsxs(TableRow$1, { className: "bg-muted/50 border-b", children: [jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.common.nameColumn }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.keys.publicKeyColumn }), jsx(TableHead, { className: "p-3 text-right text-sm whitespace-nowrap text-[#646464]", children: labels.common.actionsColumn })] }) }), jsx(TableBody, { children: keys.map((key) => (jsxs(TableRow$1, { "data-testid": "lti-key-row", className: "border-b last:border-0 hover:bg-muted/40", children: [jsx(TableCell$1, { className: "p-3 text-sm font-medium text-gray-900", children: key.name }), jsx(TableCell$1, { className: "p-3 font-mono text-xs text-[#646464]", children: truncateMiddle(key.public_key, 40) }), jsx(TableCell$1, { className: "p-3 text-right", children: jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsx(Button$1, { type: "button", variant: "ghost", size: "icon", "aria-label": labels.keys.actionsAria(key.name), children: jsx(EllipsisVertical, { className: "h-4 w-4" }) }) }), jsxs(DropdownMenuContent, { align: "end", children: [jsxs(DropdownMenuItem, { onClick: () => setSelectedKey(key), children: [jsx(Pencil, { className: "mr-2 h-4 w-4" }), labels.common.edit] }), jsxs(DropdownMenuItem, { className: "text-red-600 focus:text-red-700", onClick: () => setKeyToDelete(key), children: [jsx(Trash2, { className: "mr-2 h-4 w-4" }), labels.common.delete] })] })] }) })] }, key.id))) })] }) }), isFetching && (jsx("p", { className: "px-3 py-2 text-xs text-gray-400", children: labels.common.refreshing }))] })), jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: busy
|
|
270145
|
+
return (jsxs("div", { className: "space-y-4", "data-testid": "lti-keys-section", children: [jsxs("div", { className: "flex flex-col items-start justify-between gap-3 sm:flex-row sm:items-center", children: [jsx("p", { className: "text-xs text-gray-600", children: labels.keys.description }), jsxs(Button$1, { onClick: () => setShowCreate(true), size: "sm", "data-testid": "lti-key-create-button", className: "cursor-pointer whitespace-nowrap bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: [jsx(Plus, { className: "h-4 w-4" }), labels.keys.createButton] })] }), busy ? (jsx("div", { className: "flex w-full items-center justify-center py-10", children: jsx(Spinner, {}) })) : keys.length === 0 ? (jsxs("div", { className: "flex flex-col items-center justify-center gap-3 rounded-md border border-dashed border-gray-200 py-12 text-center", "data-testid": "lti-keys-empty", children: [jsx(KeyRound, { className: "h-8 w-8 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm text-[#646464]", children: labels.keys.empty })] })) : (jsxs("div", { className: "overflow-hidden rounded-md border", children: [jsx("div", { className: "overflow-x-auto", children: jsxs(Table$1, { className: "min-w-full", children: [jsx(TableHeader$1, { children: jsxs(TableRow$1, { className: "bg-muted/50 border-b", children: [jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.common.nameColumn }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.keys.publicKeyColumn }), jsx(TableHead, { className: "p-3 text-right text-sm whitespace-nowrap text-[#646464]", children: labels.common.actionsColumn })] }) }), jsx(TableBody, { children: keys.map((key) => (jsxs(TableRow$1, { "data-testid": "lti-key-row", className: "border-b last:border-0 hover:bg-muted/40", children: [jsx(TableCell$1, { className: "p-3 text-sm font-medium text-gray-900", children: key.name }), jsx(TableCell$1, { className: "p-3 font-mono text-xs text-[#646464]", children: truncateMiddle(key.public_key, 40) }), jsx(TableCell$1, { className: "p-3 text-right", children: jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsx(Button$1, { type: "button", variant: "ghost", size: "icon", "aria-label": labels.keys.actionsAria(key.name), children: jsx(EllipsisVertical, { className: "h-4 w-4" }) }) }), jsxs(DropdownMenuContent, { align: "end", children: [jsxs(DropdownMenuItem, { onClick: () => setSelectedKey(key), children: [jsx(Pencil, { className: "mr-2 h-4 w-4" }), labels.common.edit] }), jsxs(DropdownMenuItem, { className: "text-red-600 focus:text-red-700", onClick: () => setKeyToDelete(key), children: [jsx(Trash2, { className: "mr-2 h-4 w-4" }), labels.common.delete] })] })] }) })] }, key.id))) })] }) }), isFetching && (jsx("p", { className: "px-3 py-2 text-xs text-gray-400", children: labels.common.refreshing }))] })), jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: busy }), showCreate && (jsx(KeyCreateModal, { isOpen: showCreate, onClose: () => setShowCreate(false), platformKey: platformKey, labels: labels })), selectedKey && (jsx(KeyDetailModal, { isOpen: Boolean(selectedKey), onClose: () => setSelectedKey(null), platformKey: platformKey, ltiKey: selectedKey, labels: labels })), keyToDelete && (jsx(KeyDeleteModal, { isOpen: Boolean(keyToDelete), onClose: () => setKeyToDelete(null), platformKey: platformKey, ltiKey: keyToDelete, labels: labels }))] }));
|
|
269592
270146
|
}
|
|
269593
270147
|
|
|
269594
270148
|
function FieldError({ field, }) {
|
|
@@ -269727,7 +270281,7 @@ function ToolsSection({ identity, labels }) {
|
|
|
269727
270281
|
return (jsxs("div", { className: "space-y-4", "data-testid": "lti-tools-section", children: [jsxs("div", { className: "flex flex-col items-start justify-between gap-3 sm:flex-row sm:items-center", children: [jsx("p", { className: "text-xs text-gray-600", children: labels.tools.description }), jsxs(Button$1, { onClick: () => setShowCreate(true), size: "sm", "data-testid": "lti-tool-create-button", className: "cursor-pointer whitespace-nowrap bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: [jsx(Plus, { className: "h-4 w-4" }), labels.tools.createButton] })] }), busy ? (jsx("div", { className: "flex w-full items-center justify-center py-10", children: jsx(Spinner, {}) })) : !tools || tools.length === 0 ? (jsxs("div", { className: "flex flex-col items-center justify-center gap-3 rounded-md border border-dashed border-gray-200 py-12 text-center", "data-testid": "lti-tools-empty", children: [jsx(Wrench, { className: "h-8 w-8 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm text-[#646464]", children: labels.tools.empty })] })) : (jsxs("div", { className: "overflow-hidden rounded-md border", children: [jsx("div", { className: "overflow-x-auto", children: jsxs(Table$1, { className: "min-w-full", children: [jsx(TableHeader$1, { children: jsxs(TableRow$1, { className: "bg-muted/50 border-b", children: [jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.common.nameColumn }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.tools.issuerColumn }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.tools.clientIdColumn }), jsx(TableHead, { className: "p-3 text-right text-sm whitespace-nowrap text-[#646464]", children: labels.common.actionsColumn })] }) }), jsx(TableBody, { children: tools.map((tool) => (jsxs(TableRow$1, { "data-testid": "lti-tool-row", className: "cursor-pointer border-b last:border-0 hover:bg-muted/40", onClick: () => setEditingTool(tool), children: [jsx(TableCell$1, { className: "p-3 text-sm font-medium text-gray-900", children: tool.title }), jsx(TableCell$1, { className: "max-w-[260px] truncate p-3 text-sm text-[#646464]", children: tool.issuer }), jsx(TableCell$1, { className: "max-w-[200px] truncate p-3 text-sm text-[#646464]", children: tool.client_id }), jsx(TableCell$1, { className: "p-3 text-right", children: jsx(Button$1, { type: "button", variant: "outline", size: "icon", "aria-label": labels.tools.editAria(tool.title), onClick: (event) => {
|
|
269728
270282
|
event.stopPropagation();
|
|
269729
270283
|
setEditingTool(tool);
|
|
269730
|
-
}, children: jsx(Pencil, { className: "h-4 w-4" }) }) })] }, tool.id))) })] }) }), isFetching && (jsx("p", { className: "px-3 py-2 text-xs text-gray-400", children: labels.common.refreshing }))] })), jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: busy
|
|
270284
|
+
}, children: jsx(Pencil, { className: "h-4 w-4" }) }) })] }, tool.id))) })] }) }), isFetching && (jsx("p", { className: "px-3 py-2 text-xs text-gray-400", children: labels.common.refreshing }))] })), jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: busy }), showCreate && (jsx(ToolModal, { isOpen: showCreate, onClose: () => setShowCreate(false), platformKey: platformKey, labels: labels })), editingTool && (jsx(ToolModal, { isOpen: Boolean(editingTool), onClose: () => setEditingTool(null), platformKey: platformKey, tool: editingTool, labels: labels }))] }));
|
|
269731
270285
|
}
|
|
269732
270286
|
|
|
269733
270287
|
function ToolEndpointsSection({ identity, labels, }) {
|
|
@@ -273376,7 +273930,15 @@ function StatusBadge({ status }) {
|
|
|
273376
273930
|
: 'bg-gray-100 text-gray-600';
|
|
273377
273931
|
return (jsx("span", { className: cn('inline-flex rounded-full px-2 py-0.5 text-xs font-medium', color), children: upper !== null && upper !== void 0 ? upper : '—' }));
|
|
273378
273932
|
}
|
|
273379
|
-
function AgentEvaluationTab({
|
|
273933
|
+
function AgentEvaluationTab({ userIsStudent: userIsStudentProp, ...props }) {
|
|
273934
|
+
var _a;
|
|
273935
|
+
const ctx = useAgentSettings();
|
|
273936
|
+
const userIsStudent = (_a = userIsStudentProp !== null && userIsStudentProp !== void 0 ? userIsStudentProp : ctx.userIsStudent) !== null && _a !== void 0 ? _a : false;
|
|
273937
|
+
if (userIsStudent)
|
|
273938
|
+
return null;
|
|
273939
|
+
return jsx(AgentEvaluationTabContent, { ...props });
|
|
273940
|
+
}
|
|
273941
|
+
function AgentEvaluationTabContent({ getLLMProviderDetails, labels: labelsOverride, PaginationComponent, }) {
|
|
273380
273942
|
var _a, _b;
|
|
273381
273943
|
const { tenantKey, mentorId, username } = useAgentSettings();
|
|
273382
273944
|
const dispatch = useDispatch();
|
|
@@ -277517,7 +278079,7 @@ const CODE_FILE_EXTENSIONS = new Set([
|
|
|
277517
278079
|
'css',
|
|
277518
278080
|
'sh',
|
|
277519
278081
|
]);
|
|
277520
|
-
function Chat({ mode = 'default', isPreviewMode = false, hasBorder = true, isInCanvasView = false, config, redirectToAuthSpa, username, userTenants, visitingTenant, axdToken, mentorId, tenantKey, userIsStudent, isPublicRoute, showConversationStarters = false, showExploreMentors = false, projectId, }) {
|
|
278082
|
+
function Chat({ mode = 'default', isPreviewMode = false, hasBorder = true, isInCanvasView = false, config, redirectToAuthSpa, username, userTenants, visitingTenant, axdToken, mentorId, tenantKey, userIsStudent, isPublicRoute, showConversationStarters = false, showExploreMentors = false, projectId, slashSkills, slashSkillsLoading = false, }) {
|
|
277521
278083
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
|
|
277522
278084
|
const t = useT();
|
|
277523
278085
|
const { metadata } = useTenantContext();
|
|
@@ -278546,7 +279108,7 @@ function Chat({ mode = 'default', isPreviewMode = false, hasBorder = true, isInC
|
|
|
278546
279108
|
!(messages.length > 0 &&
|
|
278547
279109
|
((_g = messages[messages.length - 1]) === null || _g === void 0 ? void 0 : _g.role) === 'assistant' &&
|
|
278548
279110
|
((_h = messages[messages.length - 1]) === null || _h === void 0 ? void 0 : _h.artifactVersions) &&
|
|
278549
|
-
((_l = (_k = (_j = messages[messages.length - 1]) === null || _j === void 0 ? void 0 : _j.artifactVersions) === null || _k === void 0 ? void 0 : _k.length) !== null && _l !== void 0 ? _l : 0) > 0) && jsx(LoadingMessage, { mentorName: mentorName, profileImage: profileImage }), !showingSharedChat && guidedPrompts] }) }) }), jsx("div", { className: "flex-shrink-0 overflow-y-auto border-t border-gray-200 bg-white p-3 [scrollbar-gutter:stable]", children: jsx(ChatInputForm, { mentorId: mentorId, userIsStudent: userIsStudent, isPublicRoute: isPublicRoute, sessionId: sessionId, onSubmit: handleSubmit, stopGenerating: stopGenerating, onScreenSharingClick: () => {
|
|
279111
|
+
((_l = (_k = (_j = messages[messages.length - 1]) === null || _j === void 0 ? void 0 : _j.artifactVersions) === null || _k === void 0 ? void 0 : _k.length) !== null && _l !== void 0 ? _l : 0) > 0) && jsx(LoadingMessage, { mentorName: mentorName, profileImage: profileImage }), !showingSharedChat && guidedPrompts] }) }) }), jsx("div", { className: "flex-shrink-0 overflow-y-auto border-t border-gray-200 bg-white p-3 [scrollbar-gutter:stable]", children: jsx(ChatInputForm, { mentorId: mentorId, userIsStudent: userIsStudent, isPublicRoute: isPublicRoute, slashSkills: slashSkills, slashSkillsLoading: slashSkillsLoading, sessionId: sessionId, onSubmit: handleSubmit, stopGenerating: stopGenerating, onScreenSharingClick: () => {
|
|
278550
279112
|
var _a;
|
|
278551
279113
|
if (enableChatPopupActions && isInIframe()) {
|
|
278552
279114
|
sendMessageToParentWebsite({
|
|
@@ -278578,7 +279140,7 @@ function Chat({ mode = 'default', isPreviewMode = false, hasBorder = true, isInC
|
|
|
278578
279140
|
height: '100%',
|
|
278579
279141
|
}, children: [jsx(CanvasView$1, { canvasTitle: canvasState.title, canvasContent: canvasState.content, canvasType: canvasState.type, artifactId: canvasState.artifactId, org: canvasState.org, userId: canvasState.userId, fileExtension: canvasState.fileExtension, metadata: canvasState.metadata, sessionId: sessionId, tenantKey: tenantKey, refreshTrigger: canvasRefreshTrigger, sendMessage: (text, options) => {
|
|
278580
279142
|
sendMessage(activeTab, text, options);
|
|
278581
|
-
}, onClose: handleCloseCanvas }, `${(_m = canvasState.artifactId) !== null && _m !== void 0 ? _m : 'canvas'}-${canvasRefreshTrigger}`), jsx("div", { className: "flex-shrink-0 border-t border-gray-200 bg-white p-3 md:hidden", children: jsx(ChatInputForm, { mentorId: mentorId, userIsStudent: userIsStudent, isPublicRoute: isPublicRoute, sessionId: sessionId, onSubmit: handleSubmit, stopGenerating: stopGenerating, onScreenSharingClick: () => {
|
|
279143
|
+
}, onClose: handleCloseCanvas }, `${(_m = canvasState.artifactId) !== null && _m !== void 0 ? _m : 'canvas'}-${canvasRefreshTrigger}`), jsx("div", { className: "flex-shrink-0 border-t border-gray-200 bg-white p-3 md:hidden", children: jsx(ChatInputForm, { mentorId: mentorId, userIsStudent: userIsStudent, isPublicRoute: isPublicRoute, slashSkills: slashSkills, slashSkillsLoading: slashSkillsLoading, sessionId: sessionId, onSubmit: handleSubmit, stopGenerating: stopGenerating, onScreenSharingClick: () => {
|
|
278582
279144
|
var _a;
|
|
278583
279145
|
if (enableChatPopupActions && isInIframe()) {
|
|
278584
279146
|
sendMessageToParentWebsite({
|
|
@@ -278625,7 +279187,7 @@ function Chat({ mode = 'default', isPreviewMode = false, hasBorder = true, isInC
|
|
|
278625
279187
|
(isAdvancedMode ||
|
|
278626
279188
|
isEmbeddedMode ||
|
|
278627
279189
|
(messages.length > 0 &&
|
|
278628
|
-
(messages[0].role === 'assistant' ? messages.slice(1) : messages).length > 0)) && (jsx("div", { className: "flex-shrink-0 overflow-y-auto pb-3.5 [scrollbar-gutter:stable]", children: jsx(ChatInputForm, { mentorId: mentorId, userIsStudent: userIsStudent, isPublicRoute: isPublicRoute, sessionId: (_u = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[mentorId]) !== null && _u !== void 0 ? _u : sessionId, onSubmit: handleSubmit, stopGenerating: stopGenerating, onScreenSharingClick: () => {
|
|
279190
|
+
(messages[0].role === 'assistant' ? messages.slice(1) : messages).length > 0)) && (jsx("div", { className: "flex-shrink-0 overflow-y-auto pb-3.5 [scrollbar-gutter:stable]", children: jsx(ChatInputForm, { mentorId: mentorId, userIsStudent: userIsStudent, isPublicRoute: isPublicRoute, slashSkills: slashSkills, slashSkillsLoading: slashSkillsLoading, sessionId: (_u = cachedSessionId === null || cachedSessionId === void 0 ? void 0 : cachedSessionId[mentorId]) !== null && _u !== void 0 ? _u : sessionId, onSubmit: handleSubmit, stopGenerating: stopGenerating, onScreenSharingClick: () => {
|
|
278629
279191
|
var _a;
|
|
278630
279192
|
if (enableChatPopupActions && isInIframe()) {
|
|
278631
279193
|
sendMessageToParentWebsite({
|
|
@@ -329934,5 +330496,5 @@ var index_es = /*#__PURE__*/Object.freeze({
|
|
|
329934
330496
|
vectorsRatio: vectorsRatio
|
|
329935
330497
|
});
|
|
329936
330498
|
|
|
329937
|
-
export { AGENT_ACCESS_TAB_LABELS, AGENT_ANALYTICS_TAB_LABELS, AGENT_API_TAB_LABELS, AGENT_DATASETS_TAB_LABELS, AGENT_DISCLAIMERS_TAB_LABELS, AGENT_EMBED_TAB_LABELS, AGENT_EVALUATION_TAB_LABELS, AGENT_GRADER_TAB_LABELS, AGENT_HISTORY_TAB_LABELS, AGENT_HUMAN_SUPPORT_TAB_LABELS, AGENT_LLM_TAB_LABELS, AGENT_LTI_TAB_LABELS, AGENT_MEMORY_TAB_LABELS, AGENT_PICKER_LABELS, AGENT_PRIVACY_TAB_LABELS, AGENT_PROMPTS_TAB_LABELS, AGENT_SAFETY_TAB_LABELS, AGENT_SCREENSHARE_TAB_LABELS, AGENT_SEARCH_LABELS, AGENT_SETTINGS_TAB_LABELS, AGENT_TASKS_TAB_LABELS, AGENT_TOOLS_TAB_LABELS, AGENT_VOICE_TAB_LABELS, Account, AgentAccessTab, AgentAnalyticsTab, AgentApiTab, AgentCard, AgentDatasetsTab, AgentDisclaimersTab, AgentEmbedTab, AgentEmptyState, AgentEvaluationTab, AgentGraderTab, AgentHistoryTab, AgentHumanSupportTab, AgentLLMTab, AgentLtiTab, AgentMemoryTab, AgentPrivacyTab, AgentPromptsTab, AgentSafetyTab, AgentScreenShareTab, AgentSearch, AgentSearchFilters, AgentSearchInput, AgentSettingsProvider, AgentSettingsTab, AgentTasksTab, AgentToolsTab, AgentVoiceTab, AppSidebar, CATALOGS, Chat, ClientErrorPage, ConversationStarters$1 as ConversationStarters, CopyButton, CopyMentorModal, CourseBox, CourseContentLayout, CourseContentTabPage, CreatePathwayModal, CredentialDetailModal, CredentialMiniBox, DEFAULT_ANALYTICS_HUB_TABS, DEFAULT_LOCALE, DeleteMentorModal, EMPTY_PROGRAM_SETTINGS_FORM, EdxIframe, ErrorPage, GRADING_TOOL_NAME, GreetingMethod, McpTab, MediaBox, MentorSelectionGrid, NavBar, OrganizationTab, PLATFORM_SIDEBAR_FLYOUT_ITEM_COLOR, PLATFORM_SIDEBAR_FLYOUT_TITLE_COLOR, PLATFORM_SIDEBAR_NAV_ACTIVE_BG_OPEN, PLATFORM_SIDEBAR_NAV_MUTED, PathwayDetailModal, PlatformAccountSheet, PlatformSidebar, PlatformSidebarCollapsedLabelFlyout, PlatformSidebarCollapsedNavFlyout, PlatformSidebarFooter, PlatformSidebarNavDivider, PlatformSidebarNavSection, PlatformSidebarSubNavItem, ProfileInfoCards, ProfileTabs, ProgramDetailModal, ProjectsSidebarDropdown, SUPPORTED_LOCALES, SidebarInset, SidebarProvider, SidebarTrigger, SsoLogin, StarButton, UserProfileDropdown, UserProfileModal, WebContainersI18nProvider, formatDateString, getCatalog, getLLMProviderDetails, initializeLocalStorageWithObject, isValidLocale, resolveAgentPickerLabels, resolveAgentSearchLabels, resolveSettingsTabLabels, useAgentSearch, useAgentSearchWithPagination, useAgentSettings, useAgentStar, useGetChatDetails, usePlatformSidebarFooterActions, usePlatformSidebarNavCallback, useSidebar, useT, useTimeTracker, useWebContainersI18n, useWebContainersLocale };
|
|
330499
|
+
export { AGENT_ACCESS_TAB_LABELS, AGENT_ANALYTICS_TAB_LABELS, AGENT_API_TAB_LABELS, AGENT_DATASETS_TAB_LABELS, AGENT_DISCLAIMERS_TAB_LABELS, AGENT_EMBED_TAB_LABELS, AGENT_EVALUATION_TAB_LABELS, AGENT_GRADER_TAB_LABELS, AGENT_HISTORY_TAB_LABELS, AGENT_HUMAN_SUPPORT_TAB_LABELS, AGENT_LLM_TAB_LABELS, AGENT_LTI_TAB_LABELS, AGENT_MEMORY_TAB_LABELS, AGENT_PICKER_LABELS, AGENT_PRIVACY_TAB_LABELS, AGENT_PROMPTS_TAB_LABELS, AGENT_SAFETY_TAB_LABELS, AGENT_SCREENSHARE_TAB_LABELS, AGENT_SEARCH_LABELS, AGENT_SETTINGS_TAB_LABELS, AGENT_SKILLS_TAB_LABELS, AGENT_TASKS_TAB_LABELS, AGENT_TOOLS_TAB_LABELS, AGENT_VOICE_TAB_LABELS, Account, AgentAccessTab, AgentAnalyticsTab, AgentApiTab, AgentCard, AgentDatasetsTab, AgentDisclaimersTab, AgentEmbedTab, AgentEmptyState, AgentEvaluationTab, AgentGraderTab, AgentHistoryTab, AgentHumanSupportTab, AgentLLMTab, AgentLtiTab, AgentMemoryTab, AgentPrivacyTab, AgentPromptsTab, AgentSafetyTab, AgentScreenShareTab, AgentSearch, AgentSearchFilters, AgentSearchInput, AgentSettingsProvider, AgentSettingsTab, AgentSkillsTab, AgentTasksTab, AgentToolsTab, AgentVoiceTab, AppSidebar, CATALOGS, Chat, ClientErrorPage, ConversationStarters$1 as ConversationStarters, CopyButton, CopyMentorModal, CourseBox, CourseContentLayout, CourseContentTabPage, CreatePathwayModal, CredentialDetailModal, CredentialMiniBox, DEFAULT_ANALYTICS_HUB_TABS, DEFAULT_LOCALE, DeleteMentorModal, EMPTY_PROGRAM_SETTINGS_FORM, EdxIframe, ErrorPage, GRADING_TOOL_NAME, GreetingMethod, McpTab, MediaBox, MentorSelectionGrid, NavBar, OrganizationTab, PLATFORM_SIDEBAR_FLYOUT_ITEM_COLOR, PLATFORM_SIDEBAR_FLYOUT_TITLE_COLOR, PLATFORM_SIDEBAR_NAV_ACTIVE_BG_OPEN, PLATFORM_SIDEBAR_NAV_MUTED, PathwayDetailModal, PlatformAccountSheet, PlatformSidebar, PlatformSidebarCollapsedLabelFlyout, PlatformSidebarCollapsedNavFlyout, PlatformSidebarFooter, PlatformSidebarNavDivider, PlatformSidebarNavSection, PlatformSidebarSubNavItem, ProfileInfoCards, ProfileTabs, ProgramDetailModal, ProjectsSidebarDropdown, SUPPORTED_LOCALES, SidebarInset, SidebarProvider, SidebarTrigger, SsoLogin, StarButton, UserProfileDropdown, UserProfileModal, WebContainersI18nProvider, formatDateString, getCatalog, getLLMProviderDetails, initializeLocalStorageWithObject, isValidLocale, resolveAgentPickerLabels, resolveAgentSearchLabels, resolveSettingsTabLabels, useAgentSearch, useAgentSearchWithPagination, useAgentSettings, useAgentStar, useGetChatDetails, usePlatformSidebarFooterActions, usePlatformSidebarNavCallback, useSidebar, useT, useTimeTracker, useWebContainersI18n, useWebContainersLocale };
|
|
329938
330500
|
//# sourceMappingURL=index.esm.js.map
|