@iblai/iblai-js 2.9.7 → 2.9.9

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.
@@ -895,9 +895,13 @@ function useModelDownload() {
895
895
  // if the dialog is closed and reopened mid-download (state is persisted).
896
896
  activeModel: modelId !== null && modelId !== void 0 ? modelId : 'phi3:mini',
897
897
  }));
898
- // Check disk space first
898
+ // Check disk space first. The model id lets mobile hosts budget the
899
+ // model's REAL size instead of a blanket requirement; hosts that
900
+ // don't know the id fall back to their blanket check.
899
901
  console.log('[ModelDownload] Checking disk space...');
900
- const hasSpace = await invoke(TAURI_COMMANDS.CHECK_DISK_SPACE);
902
+ const hasSpace = await invoke(TAURI_COMMANDS.CHECK_DISK_SPACE, {
903
+ model: modelId !== null && modelId !== void 0 ? modelId : 'phi3:mini',
904
+ });
901
905
  console.log('[ModelDownload] Disk space check result:', hasSpace);
902
906
  if (!hasSpace) {
903
907
  console.log('[ModelDownload] Insufficient disk space');
@@ -3983,21 +3987,21 @@ var llmTabLabels$3 = {
3983
3987
  tooLargeTitle: "This model may be too large for your system",
3984
3988
  tooLargeDescription: "{modelName} needs about {modelSize}. It may run very slowly or fail to load on this machine. Download anyway?",
3985
3989
  cancel: "Cancel",
3986
- downloadAnyway: "Download anyway",
3990
+ downloadAnyway: "Download Anyway",
3987
3991
  alreadyDownloadingTitle: "A model is already downloading",
3988
3992
  unnamedModel: "A model",
3989
3993
  alreadyDownloadingDescription: "{modelName} is being downloaded. Only one on-device model downloads at a time — wait for it to finish, or click {modelName} in the list to cancel it.",
3990
- gotIt: "Got it",
3994
+ gotIt: "Got It",
3991
3995
  announceDownloaded: "{modelName} downloaded",
3992
3996
  announceCancelled: "Download cancelled",
3993
3997
  announceFailed: "Download failed",
3994
3998
  announceStarted: "Started downloading {modelName}",
3995
3999
  localModel: {
3996
- onDevice: "On-device",
4000
+ onDevice: "On-Device",
3997
4001
  starting: "Starting…",
3998
4002
  cancel: "Cancel",
3999
- inUse: "In use",
4000
- downloadFailedRetry: "Download failedretry",
4003
+ inUse: "In Use",
4004
+ downloadFailedRetry: "Download FailedRetry",
4001
4005
  ariaDownload: "Download {modelName}, {modelSize}, on-device model",
4002
4006
  ariaStarting: "Starting download of {modelName}",
4003
4007
  ariaDownloading: "Cancel download of {modelName}, {percent} percent",
@@ -86648,9 +86652,28 @@ const LOCAL_MODELS = [
86648
86652
  id: 'phi4-mini:latest',
86649
86653
  size: '2.5 GB',
86650
86654
  tool_support: true,
86655
+ // Mobile maps phi4-mini to the 3.8B-instruct Q4_K_M build (exact file
86656
+ // size on Hugging Face: 2,491,874,688 bytes).
86657
+ mobile: { size: '2.3 GB' },
86658
+ },
86659
+ {
86660
+ name: 'Llama 3.2',
86661
+ provider: 'Meta',
86662
+ id: 'llama3.2',
86663
+ size: '2.0 GB',
86664
+ tool_support: true,
86665
+ // Mobile maps llama3.2 to the 1B-instruct Q4_K_M build.
86666
+ mobile: { size: '0.8 GB' },
86667
+ },
86668
+ {
86669
+ name: 'Qwen 3',
86670
+ provider: 'Alibaba',
86671
+ id: 'qwen3',
86672
+ size: '5.2 GB',
86673
+ tool_support: true,
86674
+ // Mobile maps qwen3 to the 1.7B Q8_0 build.
86675
+ mobile: { size: '1.8 GB' },
86651
86676
  },
86652
- { name: 'Llama 3.2', provider: 'Meta', id: 'llama3.2', size: '2.0 GB', tool_support: true },
86653
- { name: 'Qwen 3', provider: 'Alibaba', id: 'qwen3', size: '5.2 GB', tool_support: true },
86654
86677
  { name: 'Mistral', provider: 'Mistral AI', id: 'mistral', size: '4.4 GB', tool_support: true },
86655
86678
  {
86656
86679
  name: 'DeepSeek-R1',
@@ -86658,6 +86681,9 @@ const LOCAL_MODELS = [
86658
86681
  id: 'deepseek-r1',
86659
86682
  size: '5.2 GB',
86660
86683
  tool_support: true,
86684
+ // Mobile maps deepseek-r1 to the 1.5B Qwen-distill Q4_K_M build (exact
86685
+ // file size on Hugging Face: 1,117,320,800 bytes).
86686
+ mobile: { size: '1.0 GB' },
86661
86687
  },
86662
86688
  { name: 'Granite 4.1', provider: 'IBM', id: 'granite4.1:8b', size: '5.3 GB', tool_support: true },
86663
86689
  { name: 'GPT-OSS 20B', provider: 'OpenAI', id: 'gpt-oss:20b', size: '14 GB', tool_support: true },
@@ -3,7 +3,7 @@ import * as React from 'react';
3
3
  import React__default, { useState, useEffect, forwardRef, createElement as createElement$3, useLayoutEffect, createContext, useContext, useMemo, useReducer, useRef, useImperativeHandle, useCallback, isValidElement, Children, PureComponent, cloneElement, Component as Component$1, useId as useId$2, useDebugValue, lazy, Suspense } from 'react';
4
4
  import * as dataLayer from '@iblai/data-layer';
5
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, useUpdateGlobalMemoryMutation, useUpdateMentorMemoryMutation, useGetMemsearchStatusQuery, useGetUserMemorySettingsQuery, useUpdateUserMemorySettingsMutation, useGetGlobalMemoriesQuery, useGetAllMentorMemoriesQuery, useDeleteGlobalMemoryMutation, useDeleteMentorMemoryMutation, useGetAiSearchMentorsQuery, useStarMentorMutation, useUnstarMentorMutation, useGetUserChatHistoryReportsQuery, USER_CHAT_HISTORY_REPORT_ACTIVE_STATES, useCreateUserChatHistoryReportMutation, useLazyGetDownloadReportFromURLQuery, useGetUserChatHistoryReportStatusQuery, userChatHistoryApiSlice, USER_CHAT_HISTORY_QUERY_KEYS, useGetUserChatHistoryQuery, useGetUserChatHistoryFilterQuery, useGetMentorsQuery, useGetUserChatHistorySessionQuery, useInviteUserMutation, usePlatformInvitationsQuery, useCreateCatalogInvitationCourseBulkMutation, useGetCatalogInvitationsCourseQuery, useLazyPlatformUsersQuery, useLazyPlatformUserGroupsQuery, useGetPersonnalizedSearchQuery, useCreateCatalogInvitationProgramBulkMutation, useGetCatalogInvitationsProgramQuery, useUpdateUserRoleMutation, useUpdateUserStatusMutation, useUpdatePlatformUserRoleWithPoliciesMutation, usePlatformUsersQuery, useGetAccessibleUsersQuery, isPoliciesResponse, platformApiSlice, featureTags, useLazyGetRbacTeamsAccessListQuery, useCreateRbacTeamsAccessMutation, useGetRbacGroupsQuery, usePlatformUserGroupsQuery, useCreateRbacGroupMutation, useUpdateRbacGroupMutation, useDeleteRbacGroupMutation, useCreatePlatformUserGroupMutation, useUpdatePlatformUserGroupMutation, useDeletePlatformUserGroupMutation, useGetRbacGroupDetailsQuery, useGetPlatformUserGroupDetailsQuery, useGetRbacPermissionsMutation, useGetRbacRolesQuery, useCreateRbacRoleMutation, useUpdateRbacRoleMutation, useDeleteRbacRoleMutation, useGetRbacRoleDetailsQuery, useGetRbacActionsDefinitionQuery, useGetRbacResourceDiscoveryQuery, useGetRbacResourceListQuery, useGetRbacPoliciesQuery, useCreateRbacPolicyMutation, useUpdateRbacPolicyMutation, useDeleteRbacPolicyMutation, useGetRbacPolicyDetailsQuery, useGetWatchedGroupsQuery, useCreateWatchedGroupMutation, useUpdateWatchedGroupMutation, useDeleteWatchedGroupMutation, useAddWatchedUserMutation, useRemoveWatchedUserMutation, useAddWatcherMutation, useUpdateWatcherMutation, useDeleteWatcherMutation, useGetWatchedUsersQuery, useGetWatchersQuery, WATCHER_NOTIFICATION_EVENTS, WATCHER_NOTIFICATION_EVENT_LABELS, useGetApplicationFormsQuery, useGetApplicationFormDetailQuery, useCreateApplicationFormMutation, useUpdateApplicationFormMutation, useGetApplicationAdminDetailQuery, useInviteApplicationCandidateMutation, useLazyGetApplicationAttachmentFileQuery, useCreateApplicationWaiverMutation, useDeleteApplicationWaiverMutation, useSubmitApplicationOverrideMutation, useUpdateApplicationPlacementMutation, useDeleteApplicationCourseAssignmentMutation, useCreateApplicationNoteMutation, useUpdateApplicationNoteMutation, useDeleteApplicationNoteMutation, useTransitionApplicationMutation, useLinkApplicationCandidateMutation, useCreateApplicationPlacementsMutation, useGetCustomMentorsQuery, useCreateApplicationCourseAssignmentsMutation, useGetApplicationBlocksQuery, useDeleteApplicationBlockMutation, useGetApplicationsPipelineStatsQuery, useGetApplicationsPipelineQuery, useGetTenantMetadataQuery, useUpdateTenantMetadataMutation, useLazyGetTenantMetadataQuery, useDeleteApiKeyMutation, useGetApiKeyQuery, useGetApiKeyFieldPermissionsQuery, useUpdateApiKeyMutation, useGetApiKeysQuery, unwrapApiTokenList, useCreateApiKeyMutation, useCreateLLMCredentialMutation, useGetCredentialsSchemaQuery, useGetMaskedLLMCredentialsQuery, useGetLlmsQuery, useDeleteIntegrationCredentialMutation, useDeleteCredentialMutation, useCreateIntegrationCredentialMutation, useGetIntegrationCredentialsSchemaQuery, useGetMaskedIntegrationCredentialsQuery, useGetAccountBillingInfoQuery, useUpdateAutoRechargeInfoMutation, useTriggerAutoRechargeMutation, useGetAgentSpendCapQuery, useGetTenantSpendCapQuery, useListAgentUserSpendCapsQuery, useUpsertAgentSpendCapMutation, useDeleteAgentSpendCapMutation, useUpsertTenantSpendCapMutation, useDeleteTenantSpendCapMutation, useUpsertUserSpendCapMutation, useDeleteUserSpendCapMutation, useGetFinancialStatsQuery, useListAgentSpendCapsQuery, useGetCreditTransactionsQuery, useCreateStripeCustomerPortalMutation, useSetPlatformConfigurationsMutation, useGetPlatformConfigurationsQuery, useUpdatePlatformMembershipMutation, useGetPlatformMembershipQuery, useGetCustomDomainsQuery, useCreateCustomDomainMutation, useDeleteCustomDomainMutation, useGetStudentMentorCreationStatusQuery, useSetStudentMentorCreationStatusMutation, coreApiSlice, recommendationPromptTypeEnum, useGetRecommendedPromptsListQuery, useCreateRecommendedPromptMutation, useUpdateRecommendedPromptMutation, useDeleteRecommendedPromptMutation, useLazyGetPublicPlatformImageAssetFileUrlQuery, useCreatePlatformImageAssetMutation, useGetProviderConfigQuery, useCreateProviderConfigMutation, useDeleteProviderConfigMutation, useGetExternalMappingQuery, useGetCredentialsListQuery, useCreateExternalMappingMutation, useDeleteExternalMappingMutation, useGetMemsearchConfigQuery, useUpdateMemsearchConfigMutation, useGetStripeConnectStatusQuery, useStartStripeConnectOnboardingMutation, useLazyGetStripeConnectDashboardQuery, useListPaywallsQuery, useListPricesQuery, useCreatePriceMutation, useUpdatePriceMutation, useDeletePriceMutation, useGetPaywallConfigQuery, useEnablePaywallMutation, useUpdatePaywallMutation, useGetMentorMemoriesListQuery, useGetMemoryCategoriesAdminQuery, useCreateMentorMemoryMutation, useLazyGetCourseMetaDataQuery, useLazyGetCourseCompletionOutlinesQuery, useLazyGetCourseEligibilityQuery, useLazyGetEdxSSOTokenQuery, useCreateCourseEnrollmentMutation, useCreateStripeCheckoutSessionMutation, useLazyGetCourseProgressQuery, useLazyGetCourseCompletionQuery, useUpdateExamAttemptMutation, useStartExamMutation, useLazyGetExamInfoQuery, useGetAgentSkillResourcesQuery, useCreateAgentSkillResourceMutation, useUpdateAgentSkillResourceMutation, useUploadAgentSkillResourceAssetMutation, useDeleteAgentSkillResourceMutation, useGetMentorSkillAssignmentsQuery, useGetAgentSkillsQuery, useCreateMentorSkillAssignmentMutation, useUpdateMentorSkillAssignmentMutation, useDeleteMentorSkillAssignmentMutation, useCreateAgentSkillMutation, useUpdateAgentSkillMutation, useDeleteAgentSkillMutation, filterSlashSkills, useGetMentorSkillAssignmentsInfiniteQuery, MENTOR_SKILL_ASSIGNMENTS_PAGE_SIZE, useUpdateUserProjectMutation, useGetTrainingDocumentsQuery, useGetVectorDocumentsQuery, useLazyGetConnectedServiceAuthUrlQuery, useCreateUserProjectMutation, useDeleteUserProjectMutation, useGetUserProjectDetailsQuery, useEditTrainingDocumentMutation, useAddTrainingDocumentMutation, useLazyGetCredentialsQuery, useGetMentorSettingsQuery, useEditMentorMutation, useUploadLightLogoMutation, useUploadDarkLogoMutation, useUpdatePlatformInfoMutation, LOGO_ENDPOINTS, useCreateEvalDatasetMutation, useAddEvalDatasetItemsMutation, useUploadEvalDatasetCsvMutation, useDeleteEvalDatasetItemMutation, useListEvalDatasetItemsQuery, evalTotalPages, useListEvalDatasetsQuery, useGetUserProjectsQuery, useCreateSessionIdMutation, useGetMentorCategoriesQuery, useGetTenantChatPrivacyConfigQuery as useGetTenantChatPrivacyConfigQuery$1, useGetCallConfigurationsQuery, useCreateCallConfigurationMutation, useUpdateCallConfigurationMutation, chatPrivacyApiSlice, useDeleteMentorMutation, useForkMentorMutation, useGetToolsQuery, useLazyGetMCPServersQuery, useOauthFindMutation, useLazyStartOAuthFlowQuery, useCreateMCPServerMutation, usePartialUpdateMCPServerMutation, useCreateMCPServerConnectionMutation, usePatchMCPServerConnectionMutation, useGetConnectedServicesQuery, useGetMCPServersQuery, useGetMCPServerConnectionsQuery, useUpdateMCPServerMutation, useDeleteMCPServerMutation, useEditMentorJsonMutation, useDisconnectServiceMutation, useGetPromptCategoriesQuery, PRIVACY_ACTIONS, PRIVACY_ENTITY_TYPES, useGetVoicesQuery, useGetVoiceQuery, isBaseAgentMentor, useGetGradeResultQuery, useOverrideGradeResultMutation, useGetChatHistoryFilterQuery, useListGradeResultsQuery, useGetMentorGraderConfigurationQuery, useListGraderCriteriaQuery, useCreateMentorGraderConfigurationMutation, useUpdateMentorGraderConfigurationMutation, useCreateGraderCriterionMutation, useUpdateGraderCriterionMutation, useDeleteGraderCriterionMutation, useGetSpendCapStatusQuery, useGetMentorPublicSettingsQuery, useGetChatHistoryQuery, useGetMentorSummariesQuery, useGetConversationMemoriesQuery, useGetSupportTicketsQuery, useGetSupportTicketMessagesQuery, useCreateSupportTicketMessageMutation, usePatchSupportTicketMutation, useCloseSupportTicketMutation, useCreateLtiMentorMutation, useUpdateLtiMentorMutation, useGetLtiMentorsQuery, useDeleteLtiMentorMutation, useCreateLtiKeyMutation, useUpdateLtiKeyMutation, useDeleteLtiKeyMutation, useGetLtiKeysQuery, useCreateLtiToolMutation, useUpdateLtiToolMutation, useGetLtiToolsQuery, useGetPlatformInfoQuery, useCreatePromptMutation, useGetPromptsSearchQuery, useUpdatePromptMutation, useCreateRedirectTokenMutation, useGetShareableLinkQuery, useCreateShareableLinkMutation, useUpdateShareableLinkMutation, useCreateDisclaimerMutation, useUpdateDisclaimerMutation, useGetDisclaimersQuery, useUpdateRbacMentorAccessMutation, useGetRbacMentorAccessListQuery, useStartEvalRunMutation, useEvaluateEvalRunMutation, useGetEvalRunQuery, useDeleteEvalScoreMutation, useListEvalRunJudgesQuery, useCreateEvalScoreMutation, useDeleteEvalRunMutation, useExportEvalRunMutation, useListEvalRunsQuery, useLazyGetEvalRunQuery, evaluationsApiSlice, EVALUATIONS_TAGS, useGetPersonnalizedMentorsQuery, useCreateCallCredentialsMutation, useGetGuidedPromptsQuery, useUpdateChatSessionSharedMutation, useUpdateMessageFeedbackMutation, useLazyGetPromptsSearchQuery, useLazyGetGuidedPromptsQuery, useGetPublicMentorsQuery, useGetPeriodicAgentsQuery, useGetPeriodicAgentLogsListQuery, useCreatePeriodicAgentMutation, useDeletePeriodicAgentMutation, useCreateMemoryCategoryMutation, useUpdateMemoryCategoryMutation, useDeleteMemoryCategoryMutation, useDeletePromptMutation, useDeleteTrainingDocumentMutation, useGetTrainingDocumentRetrainScheduleQuery, useCreateTrainingDocumentRetrainScheduleMutation, useUpdateArtifactMutation, useLazyGetArtifactVersionQuery, useLazyListArtifactVersionsQuery, useSetCurrentVersionMutation, useListArtifactVersionsQuery, useLazyGetArtifactQuery, useLazyListArtifactsQuery, useEditSessionMutation } from '@iblai/data-layer';
6
- import { removeAuthItem, setAuthItem, selectRbacPermissions, useCurrentTenant, canViewOtherUsersChatHistory, getInitials, useTenantMetadata, isPureWatcher, WithPermissions, canWriteField, useStripeUpgrade, openExternalUrl, CHAT_AREA_SIZE, isAlphaNumeric32, checkRbacPermission, selectNumberOfActiveChatMessages, useUsername, selectStreaming, isLoggedIn, TOOLS, hasRemoteAiConfig, isSafariBrowser, useShowAttachment, useShowVoiceCall, useShowVoiceRecorder, useMentorSettings, selectShowingSharedChat, useShowFreeTrialDialog, useEmbedMode, chatInputSliceSelectors, useResponsive, useAccessingPublicRoute, useVisitingTenant, useModelFileUploadCapabilities, useChatFileUpload, useVoiceChat, selectAttachedFiles, MENTOR_CHAT_DOCUMENTS_EXTENSIONS, removeFile, chatInputSliceActions, chatActions, WithFormPermissions, useTenantContext, TimeTracker, advancedTabsProperties, defaultSessionIds, pickWritableFields, ANONYMOUS_USERNAME as ANONYMOUS_USERNAME$3, redirectToAuthSpaJoinTenant, selectActiveTab, useAxdToken, useWelcomeMessage, markdownToPlainText, useCachedSessionId, use402ErrorCheck, use401TokenRefresh, selectTokenEnabled, selectToken, useServiceWorker, useUserAgreement, useAdvancedChat, sendMessageToParentWebsite, useMentorTools, useFileDragDrop, eventBus, RemoteEvents, selectEnableChatActionsPopup, advancedTabs, isInIframe, getAuthSpaJoinUrl, addMessage, clearFiles, MENTOR_VISIBILITY } from '@iblai/web-utils';
6
+ import { removeAuthItem, setAuthItem, isTauriEmbeddedLLMHost, selectRbacPermissions, useCurrentTenant, canViewOtherUsersChatHistory, getInitials, useTenantMetadata, isPureWatcher, WithPermissions, canWriteField, useStripeUpgrade, openExternalUrl, CHAT_AREA_SIZE, isAlphaNumeric32, checkRbacPermission, selectNumberOfActiveChatMessages, useUsername, selectStreaming, isLoggedIn, TOOLS, hasRemoteAiConfig, isSafariBrowser, useShowAttachment, useShowVoiceCall, useShowVoiceRecorder, useMentorSettings, selectShowingSharedChat, useShowFreeTrialDialog, useEmbedMode, chatInputSliceSelectors, useResponsive, useAccessingPublicRoute, useVisitingTenant, useModelFileUploadCapabilities, useChatFileUpload, useVoiceChat, selectAttachedFiles, MENTOR_CHAT_DOCUMENTS_EXTENSIONS, removeFile, chatInputSliceActions, chatActions, WithFormPermissions, useTenantContext, TimeTracker, advancedTabsProperties, defaultSessionIds, pickWritableFields, ANONYMOUS_USERNAME as ANONYMOUS_USERNAME$3, redirectToAuthSpaJoinTenant, selectActiveTab, useAxdToken, useWelcomeMessage, markdownToPlainText, useCachedSessionId, use402ErrorCheck, use401TokenRefresh, selectTokenEnabled, selectToken, useServiceWorker, useUserAgreement, useAdvancedChat, sendMessageToParentWebsite, useMentorTools, useFileDragDrop, eventBus, RemoteEvents, selectEnableChatActionsPopup, advancedTabs, isInIframe, getAuthSpaJoinUrl, addMessage, clearFiles, MENTOR_VISIBILITY } from '@iblai/web-utils';
7
7
  import { useDispatch, useSelector } from 'react-redux';
8
8
  import { toast } from 'sonner';
9
9
  import { useSearchParams, useParams, useRouter, usePathname } from 'next/navigation';
@@ -98770,21 +98770,21 @@ var llmTabLabels$3 = {
98770
98770
  tooLargeTitle: "This model may be too large for your system",
98771
98771
  tooLargeDescription: "{modelName} needs about {modelSize}. It may run very slowly or fail to load on this machine. Download anyway?",
98772
98772
  cancel: "Cancel",
98773
- downloadAnyway: "Download anyway",
98773
+ downloadAnyway: "Download Anyway",
98774
98774
  alreadyDownloadingTitle: "A model is already downloading",
98775
98775
  unnamedModel: "A model",
98776
98776
  alreadyDownloadingDescription: "{modelName} is being downloaded. Only one on-device model downloads at a time — wait for it to finish, or click {modelName} in the list to cancel it.",
98777
- gotIt: "Got it",
98777
+ gotIt: "Got It",
98778
98778
  announceDownloaded: "{modelName} downloaded",
98779
98779
  announceCancelled: "Download cancelled",
98780
98780
  announceFailed: "Download failed",
98781
98781
  announceStarted: "Started downloading {modelName}",
98782
98782
  localModel: {
98783
- onDevice: "On-device",
98783
+ onDevice: "On-Device",
98784
98784
  starting: "Starting…",
98785
98785
  cancel: "Cancel",
98786
- inUse: "In use",
98787
- downloadFailedRetry: "Download failedretry",
98786
+ inUse: "In Use",
98787
+ downloadFailedRetry: "Download FailedRetry",
98788
98788
  ariaDownload: "Download {modelName}, {modelSize}, on-device model",
98789
98789
  ariaStarting: "Starting download of {modelName}",
98790
98790
  ariaDownloading: "Cancel download of {modelName}, {percent} percent",
@@ -130354,9 +130354,28 @@ const LOCAL_MODELS = [
130354
130354
  id: 'phi4-mini:latest',
130355
130355
  size: '2.5 GB',
130356
130356
  tool_support: true,
130357
+ // Mobile maps phi4-mini to the 3.8B-instruct Q4_K_M build (exact file
130358
+ // size on Hugging Face: 2,491,874,688 bytes).
130359
+ mobile: { size: '2.3 GB' },
130360
+ },
130361
+ {
130362
+ name: 'Llama 3.2',
130363
+ provider: 'Meta',
130364
+ id: 'llama3.2',
130365
+ size: '2.0 GB',
130366
+ tool_support: true,
130367
+ // Mobile maps llama3.2 to the 1B-instruct Q4_K_M build.
130368
+ mobile: { size: '0.8 GB' },
130369
+ },
130370
+ {
130371
+ name: 'Qwen 3',
130372
+ provider: 'Alibaba',
130373
+ id: 'qwen3',
130374
+ size: '5.2 GB',
130375
+ tool_support: true,
130376
+ // Mobile maps qwen3 to the 1.7B Q8_0 build.
130377
+ mobile: { size: '1.8 GB' },
130357
130378
  },
130358
- { name: 'Llama 3.2', provider: 'Meta', id: 'llama3.2', size: '2.0 GB', tool_support: true },
130359
- { name: 'Qwen 3', provider: 'Alibaba', id: 'qwen3', size: '5.2 GB', tool_support: true },
130360
130379
  { name: 'Mistral', provider: 'Mistral AI', id: 'mistral', size: '4.4 GB', tool_support: true },
130361
130380
  {
130362
130381
  name: 'DeepSeek-R1',
@@ -130364,6 +130383,9 @@ const LOCAL_MODELS = [
130364
130383
  id: 'deepseek-r1',
130365
130384
  size: '5.2 GB',
130366
130385
  tool_support: true,
130386
+ // Mobile maps deepseek-r1 to the 1.5B Qwen-distill Q4_K_M build (exact
130387
+ // file size on Hugging Face: 1,117,320,800 bytes).
130388
+ mobile: { size: '1.0 GB' },
130367
130389
  },
130368
130390
  { name: 'Granite 4.1', provider: 'IBM', id: 'granite4.1:8b', size: '5.3 GB', tool_support: true },
130369
130391
  { name: 'GPT-OSS 20B', provider: 'OpenAI', id: 'gpt-oss:20b', size: '14 GB', tool_support: true },
@@ -130392,6 +130414,23 @@ const LOCAL_MODELS = [
130392
130414
  tool_support: true,
130393
130415
  },
130394
130416
  ];
130417
+ /**
130418
+ * The catalog as this device can actually serve it. Desktop (and plain web)
130419
+ * sees everything; Tauri iOS sees only models with phone-sized weights
130420
+ * (`mobile` on {@link LocalModel}) — its embedded runtime rejects the rest, so
130421
+ * listing them would only offer downloads that end in an error.
130422
+ */
130423
+ function localModelsForThisDevice() {
130424
+ return isTauriEmbeddedLLMHost() ? LOCAL_MODELS.filter((m) => m.mobile) : LOCAL_MODELS;
130425
+ }
130426
+ /**
130427
+ * The download size to show for a model on THIS device: the phone build's size
130428
+ * on Tauri iOS, the desktop Ollama size everywhere else. Feed this (not
130429
+ * `model.size`) to anything user-facing, size-warning math included.
130430
+ */
130431
+ function localModelDisplaySize(model) {
130432
+ return isTauriEmbeddedLLMHost() && model.mobile ? model.mobile.size : model.size;
130433
+ }
130395
130434
  /**
130396
130435
  * Fraction of the machine's memory above which a model is treated as "too large"
130397
130436
  * and a confirmation is required before downloading. TESTING VALUE — set low (1%)
@@ -130435,7 +130474,8 @@ function usableMemoryBytes(systemMemory) {
130435
130474
  */
130436
130475
  function modelExceedsCapacity(model, systemMemory) {
130437
130476
  const capacity = usableMemoryBytes(systemMemory);
130438
- const modelBytes = parseModelSizeBytes(model.size);
130477
+ // Display size = the build THIS device would download (phone build on iOS).
130478
+ const modelBytes = parseModelSizeBytes(localModelDisplaySize(model));
130439
130479
  if (modelBytes == null)
130440
130480
  return false;
130441
130481
  // Unknown memory (capacity 0) → don't warn; the download simply proceeds
@@ -264626,9 +264666,13 @@ function useModelDownload() {
264626
264666
  // if the dialog is closed and reopened mid-download (state is persisted).
264627
264667
  activeModel: modelId !== null && modelId !== void 0 ? modelId : 'phi3:mini',
264628
264668
  }));
264629
- // Check disk space first
264669
+ // Check disk space first. The model id lets mobile hosts budget the
264670
+ // model's REAL size instead of a blanket requirement; hosts that
264671
+ // don't know the id fall back to their blanket check.
264630
264672
  console.log('[ModelDownload] Checking disk space...');
264631
- const hasSpace = await invoke(TAURI_COMMANDS.CHECK_DISK_SPACE);
264673
+ const hasSpace = await invoke(TAURI_COMMANDS.CHECK_DISK_SPACE, {
264674
+ model: modelId !== null && modelId !== void 0 ? modelId : 'phi3:mini',
264675
+ });
264632
264676
  console.log('[ModelDownload] Disk space check result:', hasSpace);
264633
264677
  if (!hasSpace) {
264634
264678
  console.log('[ModelDownload] Insufficient disk space');
@@ -270077,6 +270121,12 @@ function useSelectedLocalModel() {
270077
270121
  return sel;
270078
270122
  }
270079
270123
 
270124
+ /**
270125
+ * English fallback bundle. Rendered copy comes from the i18n catalog via
270126
+ * {@link buildLLMTabLabels}; this is only used when no translate function is
270127
+ * available (e.g. `resolveLLMTabLabels()` called outside a component). Keep it
270128
+ * in sync with `llmTabLabels` in `i18n/messages/en.json`.
270129
+ */
270080
270130
  const AGENT_LLM_TAB_LABELS = {
270081
270131
  header: {
270082
270132
  title: 'LLM Configuration',
@@ -270100,21 +270150,21 @@ const AGENT_LLM_TAB_LABELS = {
270100
270150
  tooLargeTitle: 'This model may be too large for your system',
270101
270151
  tooLargeDescription: (modelName, modelSize) => `${modelName} needs about ${modelSize}. It may run very slowly or fail to load on this machine. Download anyway?`,
270102
270152
  cancel: 'Cancel',
270103
- downloadAnyway: 'Download anyway',
270153
+ downloadAnyway: 'Download Anyway',
270104
270154
  alreadyDownloadingTitle: 'A model is already downloading',
270105
270155
  unnamedModel: 'A model',
270106
270156
  alreadyDownloadingDescription: (modelName) => `${modelName} is being downloaded. Only one on-device model downloads at a time — wait for it to finish, or click ${modelName} in the list to cancel it.`,
270107
- gotIt: 'Got it',
270157
+ gotIt: 'Got It',
270108
270158
  announceDownloaded: (modelName) => `${modelName} downloaded`,
270109
270159
  announceCancelled: 'Download cancelled',
270110
270160
  announceFailed: 'Download failed',
270111
270161
  announceStarted: (modelName) => `Started downloading ${modelName}`,
270112
270162
  localModel: {
270113
- onDevice: 'On-device',
270163
+ onDevice: 'On-Device',
270114
270164
  starting: 'Starting…',
270115
270165
  cancel: 'Cancel',
270116
- inUse: 'In use',
270117
- downloadFailedRetry: 'Download failedretry',
270166
+ inUse: 'In Use',
270167
+ downloadFailedRetry: 'Download FailedRetry',
270118
270168
  ariaDownload: (modelName, modelSize) => `Download ${modelName}, ${modelSize}, on-device model`,
270119
270169
  ariaStarting: (modelName) => `Starting download of ${modelName}`,
270120
270170
  ariaDownloading: (modelName, percent) => `Cancel download of ${modelName}, ${percent} percent`,
@@ -270190,7 +270240,9 @@ function resolveLLMTabLabels(override, t) {
270190
270240
  * line beneath it. One click toggles download ⇄ cancel; once installed a click
270191
270241
  * selects it.
270192
270242
  */
270193
- function LocalModelRow({ name, size, logo, status, progress, disabled = false, disabledReason, errorMessage, onActivate, labels = AGENT_LLM_TAB_LABELS.providerModal.localModel, }) {
270243
+ function LocalModelRow({ name, size, logo, status, progress, disabled = false, disabledReason, errorMessage, onActivate, labels: labelsProp, }) {
270244
+ const t = useT();
270245
+ const labels = useMemo(() => labelsProp !== null && labelsProp !== void 0 ? labelsProp : buildLLMTabLabels(t).providerModal.localModel, [labelsProp, t]);
270194
270246
  const selected = status === 'selected';
270195
270247
  const downloading = status === 'downloading' || status === 'starting';
270196
270248
  // A resting row (nothing downloading) can still be disabled when another
@@ -270235,8 +270287,10 @@ function LocalModelRow({ name, size, logo, status, progress, disabled = false, d
270235
270287
  }), loading: "lazy" }) }), jsxs("span", { className: "relative z-10 flex min-w-0 flex-1 flex-col gap-1.5", children: [jsx("span", { className: "truncate text-sm font-medium text-[#646464] lowercase", children: name }), jsxs("span", { className: "flex min-w-0 items-center gap-1.5 text-sm text-gray-500", children: [jsx("span", { className: "flex-shrink-0 rounded bg-gray-100 px-2 py-0.5 text-sm font-medium text-gray-500", children: labels.onDevice }), status === 'not-installed' && (jsxs(Fragment$1, { children: [jsx("span", { "aria-hidden": "true", children: "\u00B7" }), jsx("span", { children: size }), jsx(Download, { className: "h-4 w-4", "aria-hidden": "true" })] })), status === 'starting' && (jsxs(Fragment$1, { children: [jsx("span", { "aria-hidden": "true", children: "\u00B7" }), jsx("span", { children: labels.starting })] })), status === 'downloading' && (jsxs(Fragment$1, { children: [jsx("span", { "aria-hidden": "true", children: "\u00B7" }), jsxs("span", { className: "tabular-nums group-hover:hidden group-focus-visible:hidden", children: [pct, "%"] }), jsxs("span", { className: "hidden items-center gap-1 text-blue-600 group-hover:flex group-focus-visible:flex", children: [jsx(X$2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }), labels.cancel] })] })), status === 'selected' && (jsxs("span", { className: "flex items-center gap-1 text-blue-600", children: [jsx(Check, { className: "h-4 w-4", "aria-hidden": "true" }), labels.inUse] })), status === 'error' && (jsxs(Fragment$1, { children: [jsx("span", { "aria-hidden": "true", children: "\u00B7" }), jsx("span", { className: "truncate text-red-500", children: errorMessage || labels.downloadFailedRetry }), jsx(RotateCcw, { className: "h-4 w-4 flex-shrink-0 text-red-500", "aria-hidden": "true" })] }))] })] })] }));
270236
270288
  }
270237
270289
 
270238
- function LLMProviderModal({ isOpen, onClose, onSelect, llmProvider, isSelecting, mentorSettings, llms, getLLMProviderDetails: getLLMProviderDetails$1 = getLLMProviderDetails, labels = AGENT_LLM_TAB_LABELS.providerModal, }) {
270239
- var _a, _b;
270290
+ function LLMProviderModal({ isOpen, onClose, onSelect, llmProvider, isSelecting, mentorSettings, llms, getLLMProviderDetails: getLLMProviderDetails$1 = getLLMProviderDetails, labels: labelsProp, }) {
270291
+ var _a;
270292
+ const t = useT();
270293
+ const labels = React__default.useMemo(() => labelsProp !== null && labelsProp !== void 0 ? labelsProp : buildLLMTabLabels(t).providerModal, [labelsProp, t]);
270240
270294
  const [searchQuery, setSearchQuery] = React__default.useState('');
270241
270295
  // On-device model download state (Tauri desktop only; `isAvailable` is false
270242
270296
  // on web, which hides every local row below).
@@ -270303,7 +270357,8 @@ function LLMProviderModal({ isOpen, onClose, onSelect, llmProvider, isSelecting,
270303
270357
  if (!isAvailable)
270304
270358
  return [];
270305
270359
  const key = getProviderName(llmProvider.name);
270306
- return LOCAL_MODELS.filter((m) => getProviderName(m.provider) === key &&
270360
+ // Per-device catalog: Tauri iOS lists only models with phone-sized weights.
270361
+ return localModelsForThisDevice().filter((m) => getProviderName(m.provider) === key &&
270307
270362
  m.name.toLowerCase().includes(searchQuery.toLowerCase()));
270308
270363
  }, [isAvailable, llmProvider.name, searchQuery]);
270309
270364
  const switchLLMAllowed = canSwitchLLm(llmProvider);
@@ -270443,11 +270498,11 @@ function LLMProviderModal({ isOpen, onClose, onSelect, llmProvider, isSelecting,
270443
270498
  }
270444
270499
  const m = item.model;
270445
270500
  const status = statusFor(m);
270446
- return (jsx(LocalModelRow, { name: m.name, size: m.size, logo: getLLMProviderDetails$1(llmProvider.name, m.name).logo, status: status, progress: sameModel(downloadingModel, m.id) ? downloadState.progress : 0, onActivate: () => activateLocal(m, status), labels: labels.localModel }, `local-${m.id}`));
270501
+ return (jsx(LocalModelRow, { name: m.name, size: localModelDisplaySize(m), logo: getLLMProviderDetails$1(llmProvider.name, m.name).logo, status: status, progress: sameModel(downloadingModel, m.id) ? downloadState.progress : 0, onActivate: () => activateLocal(m, status), labels: labels.localModel }, `local-${m.id}`));
270447
270502
  }) }), jsx(AlertDialog, { open: !!pendingModel, onOpenChange: (open) => {
270448
270503
  if (!open)
270449
270504
  setPendingModel(null);
270450
- }, children: jsxs(AlertDialogContent, { children: [jsxs(AlertDialogHeader, { children: [jsx(AlertDialogTitle, { children: labels.tooLargeTitle }), jsx(AlertDialogDescription, { children: labels.tooLargeDescription((_a = pendingModel === null || pendingModel === void 0 ? void 0 : pendingModel.name) !== null && _a !== void 0 ? _a : '', (_b = pendingModel === null || pendingModel === void 0 ? void 0 : pendingModel.size) !== null && _b !== void 0 ? _b : '') })] }), jsxs(AlertDialogFooter, { children: [jsx(AlertDialogCancel, { onClick: () => setPendingModel(null), children: labels.cancel }), jsx(AlertDialogAction, { onClick: () => {
270505
+ }, children: jsxs(AlertDialogContent, { children: [jsxs(AlertDialogHeader, { children: [jsx(AlertDialogTitle, { children: labels.tooLargeTitle }), jsx(AlertDialogDescription, { children: labels.tooLargeDescription((_a = pendingModel === null || pendingModel === void 0 ? void 0 : pendingModel.name) !== null && _a !== void 0 ? _a : '', pendingModel ? localModelDisplaySize(pendingModel) : '') })] }), jsxs(AlertDialogFooter, { children: [jsx(AlertDialogCancel, { onClick: () => setPendingModel(null), children: labels.cancel }), jsx(AlertDialogAction, { onClick: () => {
270451
270506
  if (pendingModel) {
270452
270507
  setRequestedModel(pendingModel.id);
270453
270508
  startDownload(pendingModel.id);
@@ -270482,15 +270537,18 @@ function AgentLLMTab({ showConfigurationHeader = true, mentorId: mentorIdOverrid
270482
270537
  skip: !tenantKey || !username,
270483
270538
  });
270484
270539
  // Providers that only offer on-device (local) models — surfaced as grid cards
270485
- // (Tauri desktop only) so their downloadable models are reachable even when the
270486
- // backend LLM list has no matching cloud provider.
270540
+ // (Tauri only) so their downloadable models are reachable even when the
270541
+ // backend LLM list has no matching cloud provider. Built from THIS device's
270542
+ // catalog (not the full LOCAL_MODELS list): on phones most desktop models
270543
+ // are absent, and a provider card that opens onto an empty picker is worse
270544
+ // than no card.
270487
270545
  const localOnlyProviders = React__default.useMemo(() => {
270488
270546
  if (!isTauriApp$1())
270489
270547
  return [];
270490
270548
  const cloudKeys = new Set((llmProviders !== null && llmProviders !== void 0 ? llmProviders : []).map((p) => getProviderName(p.name)));
270491
270549
  const seen = new Set();
270492
270550
  const result = [];
270493
- for (const model of LOCAL_MODELS) {
270551
+ for (const model of localModelsForThisDevice()) {
270494
270552
  const key = getProviderName(model.provider);
270495
270553
  if (cloudKeys.has(key) || seen.has(key))
270496
270554
  continue;
@@ -270501,6 +270559,16 @@ function AgentLLMTab({ showConfigurationHeader = true, mentorId: mentorIdOverrid
270501
270559
  // after the API providers.
270502
270560
  return result.sort((a, b) => compareLLMProvidersByDisplayName(a.provider, b.provider, getLLMProviderDetails$1));
270503
270561
  }, [llmProviders, getLLMProviderDetails$1]);
270562
+ // Providers this device can serve on-device models for, by normalized key.
270563
+ // Empty off Tauri on purpose: the web has no local runtime, so a zero-model
270564
+ // server provider must not stay visible just because its NAME happens to
270565
+ // match the desktop catalog (openai, google, mistral…). Both inputs are fixed
270566
+ // for the life of the webview, so this never goes stale.
270567
+ const localProviderKeys = React__default.useMemo(() => {
270568
+ if (!isTauriApp$1())
270569
+ return new Set();
270570
+ return new Set(localModelsForThisDevice().map((m) => getProviderName(m.provider)));
270571
+ }, []);
270504
270572
  // Two alphabetical groups: providers we have a usable LLM key for first, then
270505
270573
  // the ones we don't. Ordering is independent of the search filter below, so it
270506
270574
  // holds for whatever the filter leaves.
@@ -270547,6 +270615,17 @@ function AgentLLMTab({ showConfigurationHeader = true, mentorId: mentorIdOverrid
270547
270615
  // @ts-ignore
270548
270616
  permissions: (_a = mentorSettings === null || mentorSettings === void 0 ? void 0 : mentorSettings.permissions) === null || _a === void 0 ? void 0 : _a.field, enableRBAC: enableRBAC, children: ({ disabled }) => (jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4", children: [sortedLLMProviders
270549
270617
  .filter((model) => model.name.toLowerCase().includes(searchQuery.toLowerCase()))
270618
+ // A provider with no server-side models AND no on-device
270619
+ // models for this device would open an empty picker —
270620
+ // hide it instead. The mentor's ACTIVE provider is exempt:
270621
+ // hiding what the mentor currently uses would be more
270622
+ // confusing than an explainable empty state.
270623
+ .filter((model) => {
270624
+ var _a, _b;
270625
+ return ((_b = (_a = model.chat_models) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0 ||
270626
+ getProviderName(model.name) === activeProviderKey ||
270627
+ localProviderKeys.has(getProviderName(model.name));
270628
+ })
270550
270629
  .map((model) => {
270551
270630
  const providerDetails = getLLMProviderDetails$1(model.name);
270552
270631
  const isActive = !!activeProviderKey && getProviderName(model.name) === activeProviderKey;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iblai/iblai-js",
3
- "version": "2.9.7",
3
+ "version": "2.9.9",
4
4
  "description": "Unified JavaScript SDK for IBL.ai — re-exports data-layer, web-containers, and web-utils under a single package",
5
5
  "type": "module",
6
6
  "engines": {
@@ -78,8 +78,8 @@
78
78
  "winston": "3.19.0",
79
79
  "@iblai/data-layer": "1.13.2",
80
80
  "@iblai/mcp": "1.12.10",
81
- "@iblai/web-containers": "1.19.10",
82
- "@iblai/web-utils": "2.4.4"
81
+ "@iblai/web-containers": "1.19.11",
82
+ "@iblai/web-utils": "2.4.6"
83
83
  },
84
84
  "peerDependencies": {
85
85
  "@iblai/iblai-api": "4.166.0-ai",