diff --git a/apps/chat/src/components/Chat/ChatSettings/ConversationSettings.tsx b/apps/chat/src/components/Chat/ChatSettings/ConversationSettings.tsx index 1fe73ae73..7b18b1161 100644 --- a/apps/chat/src/components/Chat/ChatSettings/ConversationSettings.tsx +++ b/apps/chat/src/components/Chat/ChatSettings/ConversationSettings.tsx @@ -99,7 +99,11 @@ export const ConversationSettings = Inversify.register( const isPlayback = !!conversation.playback?.isPlayback; if (!model) { - return {t('Agent is not available')}; + return ( + + {t('Agent is not available')} + + ); } if (!doesModelHaveSettings(model)) { diff --git a/apps/chat/src/components/Chat/ModelList.tsx b/apps/chat/src/components/Chat/ModelList.tsx index f6adaf1b4..e4a6544d2 100644 --- a/apps/chat/src/components/Chat/ModelList.tsx +++ b/apps/chat/src/components/Chat/ModelList.tsx @@ -354,7 +354,7 @@ export const ModelList = ({ const handleEdit = useCallback( (currentEntity: DialAIEntityModel) => { - dispatch(ApplicationActions.get({ applicationId: currentEntity.id })); + dispatch(ApplicationActions.get(currentEntity.id)); handleOpenApplicationModal(getApplicationType(currentEntity)); }, [dispatch, handleOpenApplicationModal], diff --git a/apps/chat/src/components/Chat/Publish/PublicationChatControls.tsx b/apps/chat/src/components/Chat/Publish/PublicationChatControls.tsx index 23a74064c..2449b7a9d 100644 --- a/apps/chat/src/components/Chat/Publish/PublicationChatControls.tsx +++ b/apps/chat/src/components/Chat/Publish/PublicationChatControls.tsx @@ -133,9 +133,9 @@ export function PublicationControlsView< unselectConversation(); unselectPrompt(); dispatch( - ApplicationActions.get({ - applicationId: resourcesToReview[publicationIdx + offset].reviewUrl, - }), + ApplicationActions.get( + resourcesToReview[publicationIdx + offset].reviewUrl, + ), ); dispatch(PublicationActions.setIsApplicationReview(true)); } diff --git a/apps/chat/src/components/Chat/Publish/PublicationHandler.tsx b/apps/chat/src/components/Chat/Publish/PublicationHandler.tsx index c21bd6bd2..6f407877e 100644 --- a/apps/chat/src/components/Chat/Publish/PublicationHandler.tsx +++ b/apps/chat/src/components/Chat/Publish/PublicationHandler.tsx @@ -284,10 +284,13 @@ export function PublicationHandler({ publication }: Props) { }; const startApplicationsReview = () => { - const applicationId = applicationsToReviewIds.length - ? applicationsToReviewIds[0].reviewUrl - : reviewedApplicationsIds[0].reviewUrl; - dispatch(ApplicationActions.get({ applicationId })); + dispatch( + ApplicationActions.get( + applicationsToReviewIds.length + ? applicationsToReviewIds[0].reviewUrl + : reviewedApplicationsIds[0].reviewUrl, + ), + ); dispatch(PublicationActions.setIsApplicationReview(true)); }; diff --git a/apps/chat/src/components/Chat/TalkTo/TalkToModal.tsx b/apps/chat/src/components/Chat/TalkTo/TalkToModal.tsx index cdce7fc56..529adcfa9 100644 --- a/apps/chat/src/components/Chat/TalkTo/TalkToModal.tsx +++ b/apps/chat/src/components/Chat/TalkTo/TalkToModal.tsx @@ -229,7 +229,7 @@ const TalkToModalView = ({ const handleEditApplication = useCallback( (entity: DialAIEntityModel) => { - dispatch(ApplicationActions.get({ applicationId: entity.id })); + dispatch(ApplicationActions.get(entity.id)); setEditModel(entity); }, [dispatch], diff --git a/apps/chat/src/components/Marketplace/ApplicationCard.tsx b/apps/chat/src/components/Marketplace/ApplicationCard.tsx index 56236355d..9ce75bf1a 100644 --- a/apps/chat/src/components/Marketplace/ApplicationCard.tsx +++ b/apps/chat/src/components/Marketplace/ApplicationCard.tsx @@ -339,7 +339,7 @@ export const ApplicationCard = ({ triggerIconSize={18} className="m-0 xl:invisible group-hover:xl:visible" /> - {!isMyApp && !entity.sharedWithMe && ( + {!isMyApp && ( )} - {!entity.sharedWithMe && - (isMyApp ? ( - - - - ) : ( - + - - ))} + + + + ) : ( + + + + )} {isApplicationId(entity.id) && (isMyApp || isPublicApp) && ( diff --git a/apps/chat/src/components/Marketplace/ApplicationDetails/ApplicationHeader.tsx b/apps/chat/src/components/Marketplace/ApplicationDetails/ApplicationHeader.tsx index 1421a2878..abeea518a 100644 --- a/apps/chat/src/components/Marketplace/ApplicationDetails/ApplicationHeader.tsx +++ b/apps/chat/src/components/Marketplace/ApplicationDetails/ApplicationHeader.tsx @@ -59,6 +59,34 @@ export const ApplicationDetailsHeader = ({ entity }: Props) => { const isApplicationsSharingEnabled = useAppSelector((state) => SettingsSelectors.isFeatureEnabled(state, Feature.ApplicationsSharing), ); + // const dispatch = useAppDispatch(); + + // const contextMenuItems = useMemo( + // () => [ + // { + // BrandIcon: IconLink, + // text: t('Copy link'), + // onClick: () => { + // dispatch(UIActions.showInfoToast(t('Link copied'))); + // }, + // }, + // { + // BrandIcon: IconBrandFacebook, + // text: t('Share via Facebook'), + // onClick: () => { + // return 'Share via Facebook'; + // }, + // }, + // { + // BrandIcon: IconBrandX, + // text: t('Share via X'), + // onClick: () => { + // return 'Share via X'; + // }, + // }, + // ], + // [dispatch, t], + // ); return (
@@ -102,7 +130,57 @@ export const ApplicationDetailsHeader = ({ entity }: Props) => { + {/*
+ + + {t('Share')} + + } + > +
+
+ +
{entity.name}
+
+
+ {contextMenuItems.map(({ BrandIcon, text, ...props }) => ( + + + {text} + + } + className="flex w-full items-center gap-3 px-3 py-2 hover:bg-accent-primary-alpha" + {...props} + /> + ))} +
+
+
+ +
*/} + {/*

+ {application.title} +

*/} {isMyApp && isApplicationsSharingEnabled && ( diff --git a/apps/chat/src/components/Marketplace/TabRenderer.tsx b/apps/chat/src/components/Marketplace/TabRenderer.tsx index 6ef72cee1..c4296d5e4 100644 --- a/apps/chat/src/components/Marketplace/TabRenderer.tsx +++ b/apps/chat/src/components/Marketplace/TabRenderer.tsx @@ -313,7 +313,7 @@ export const TabRenderer = ({ screenState }: TabRendererProps) => { const handleEditApplication = useCallback( (entity: DialAIEntityModel) => { - dispatch(ApplicationActions.get({ applicationId: entity.id })); + dispatch(ApplicationActions.get(entity.id)); setApplicationModel({ entity, action: ApplicationActionType.EDIT, diff --git a/apps/chat/src/constants/marketplace.ts b/apps/chat/src/constants/marketplace.ts index a8b4e40ce..c42b304bf 100644 --- a/apps/chat/src/constants/marketplace.ts +++ b/apps/chat/src/constants/marketplace.ts @@ -1,3 +1,4 @@ +import { ApplicationType } from '../types/applications'; import { EntityType } from '../types/common'; export enum MarketplaceQueryParams { @@ -40,12 +41,21 @@ export enum SourceType { MyCustomApps = 'My Custom Apps', MyQuickApps = 'My Quick Apps', MyCodeApps = 'My Code Apps', + MyMindMaps = 'My Mindmaps', } -export const SourceTypeOrder = { +export const SourceTypeFilterOrder = { [SourceType.Public]: 1, [SourceType.SharedWithMe]: 2, [SourceType.MyCustomApps]: 3, [SourceType.MyQuickApps]: 4, [SourceType.MyCodeApps]: 5, + [SourceType.MyMindMaps]: 6, +}; + +export const ApplicationTypeToSourceType = { + [ApplicationType.CODE_APP]: SourceType.MyCodeApps, + [ApplicationType.QUICK_APP]: SourceType.MyQuickApps, + [ApplicationType.CUSTOM_APP]: SourceType.MyCustomApps, + [ApplicationType.MINDMAP]: SourceType.MyMindMaps, }; diff --git a/apps/chat/src/store/application/application.epics.ts b/apps/chat/src/store/application/application.epics.ts index 556103679..7737b4520 100644 --- a/apps/chat/src/store/application/application.epics.ts +++ b/apps/chat/src/store/application/application.epics.ts @@ -1,6 +1,5 @@ import { EMPTY, - Observable, concat, concatMap, from, @@ -11,8 +10,6 @@ import { } from 'rxjs'; import { catchError, filter, map, switchMap } from 'rxjs/operators'; -import { AnyAction } from '@reduxjs/toolkit'; - import { combineEpics } from 'redux-observable'; import { regenerateApplicationId } from '@/src/utils/app/application'; @@ -36,7 +33,6 @@ import { DeleteType } from '@/src/constants/marketplace'; import { ApplicationActions } from '../application/application.reducers'; import { AuthSelectors } from '../auth/auth.reducers'; import { ModelsActions, ModelsSelectors } from '../models/models.reducers'; -import { ShareActions, ShareSelectors } from '../share/share.reducers'; const createApplicationEpic: AppEpic = (action$) => action$.pipe( @@ -183,42 +179,17 @@ const getApplicationEpic: AppEpic = (action$, state$) => action$.pipe( filter(ApplicationActions.get.match), switchMap(({ payload }) => - ApplicationService.get(payload.applicationId).pipe( - switchMap((application) => { - if (!application) { - return of(ApplicationActions.getFail()); - } - + ApplicationService.get(payload).pipe( + map((application) => { const modelsMap = ModelsSelectors.selectModelsMap(state$.value); - const modelFromState = modelsMap[application.reference]; - - const actions: Observable[] = []; - actions.push( - of( - ApplicationActions.getSuccess({ + return application + ? ApplicationActions.getSuccess({ ...application, - sharedWithMe: modelFromState?.sharedWithMe, - permissions: modelFromState?.permissions, - isShared: modelFromState?.isShared, - }), - ), - ); - - if (payload.isForSharing) { - const permissionsFromState = ShareSelectors.selectSharePermissions( - state$.value, - ); - actions.push( - of( - ShareActions.shareApplication({ - resourceId: application.id, - permissions: permissionsFromState, - }), - ), - ); - } - - return concat(...actions); + sharedWithMe: modelsMap[application.reference]?.sharedWithMe, + permissions: modelsMap[application.reference]?.permissions, + isShared: modelsMap[application.reference]?.isShared, + }) + : ApplicationActions.getFail(); }), catchError((err) => { console.error('Failed to get application:', err); diff --git a/apps/chat/src/store/application/application.reducers.ts b/apps/chat/src/store/application/application.reducers.ts index 05e983097..066ddab0a 100644 --- a/apps/chat/src/store/application/application.reducers.ts +++ b/apps/chat/src/store/application/application.reducers.ts @@ -73,10 +73,7 @@ export const applicationSlice = createSlice({ updateFail: (state) => { state.appLoading = UploadStatus.FAILED; }, - get: ( - state, - _action: PayloadAction<{ applicationId: string; isForSharing?: boolean }>, - ) => { + get: (state, _action: PayloadAction) => { state.appLoading = UploadStatus.LOADING; }, getSuccess: (state, action: PayloadAction) => { diff --git a/apps/chat/src/store/marketplace/marketplace.selectors.ts b/apps/chat/src/store/marketplace/marketplace.selectors.ts index 1fb77b01a..1d02ef0ef 100644 --- a/apps/chat/src/store/marketplace/marketplace.selectors.ts +++ b/apps/chat/src/store/marketplace/marketplace.selectors.ts @@ -1,15 +1,18 @@ import { createSelector } from '@reduxjs/toolkit'; import { + getApplicationType, isApplicationPublic, - isExecutableApp, - isQuickApp, } from '@/src/utils/app/application'; import { isMyApplication } from '@/src/utils/app/id'; import { DialAIEntityModel } from '@/src/types/models'; -import { SourceType, SourceTypeOrder } from '@/src/constants/marketplace'; +import { + ApplicationTypeToSourceType, + SourceType, + SourceTypeFilterOrder, +} from '@/src/constants/marketplace'; import { RootState } from '../index'; import { ModelsSelectors } from '../models/models.reducers'; @@ -63,20 +66,15 @@ export const selectSourceTypes = createSelector( models.forEach((model) => { if (isMyApplication(model)) { - if (isQuickApp(model)) { - sourceTypes.add(SourceType.MyQuickApps); - } else if (isExecutableApp(model)) { - sourceTypes.add(SourceType.MyCodeApps); - } else { - sourceTypes.add(SourceType.MyCustomApps); - } + const applicationType = getApplicationType(model); + sourceTypes.add(ApplicationTypeToSourceType[applicationType]); } else if (!isApplicationPublic(model)) { sourceTypes.add(SourceType.SharedWithMe); } }); return Array.from(sourceTypes).sort( - (a, b) => SourceTypeOrder[a] - SourceTypeOrder[b], + (a, b) => SourceTypeFilterOrder[a] - SourceTypeFilterOrder[b], ); }, ); diff --git a/apps/chat/src/store/models/models.epics.ts b/apps/chat/src/store/models/models.epics.ts index 7376082c9..53feb0d4a 100644 --- a/apps/chat/src/store/models/models.epics.ts +++ b/apps/chat/src/store/models/models.epics.ts @@ -176,7 +176,7 @@ const getInstalledModelIdsEpic: AppEpic = (action$, state$) => const allModels = ModelsSelectors.selectModels(state$.value); return allModels - .filter((model) => isMyApplication(model) || model.sharedWithMe) + .filter((model) => isMyApplication(model)) .map((app) => app.reference); }), switchMap((myAppIds) => { diff --git a/apps/chat/src/store/models/models.reducers.ts b/apps/chat/src/store/models/models.reducers.ts index 6726c9c63..d13855c62 100644 --- a/apps/chat/src/store/models/models.reducers.ts +++ b/apps/chat/src/store/models/models.reducers.ts @@ -3,7 +3,7 @@ import { PayloadAction, createSlice } from '@reduxjs/toolkit'; import { combineEntities } from '@/src/utils/app/common'; import { translate } from '@/src/utils/app/translation'; -import { ApplicationStatus } from '@/src/types/applications'; +import { ApplicationInfo, ApplicationStatus } from '@/src/types/applications'; import { ErrorMessage } from '@/src/types/error'; import { DialAIEntityModel, @@ -16,7 +16,7 @@ import { errorsMessages } from '@/src/constants/errors'; import { DeleteType } from '@/src/constants/marketplace'; import * as ModelsSelectors from './models.selectors'; -import { ModelUpdatedValues, ModelsState } from './models.types'; +import { ModelsState } from './models.types'; import { UploadStatus } from '@epam/ai-dial-shared'; import cloneDeep from 'lodash-es/cloneDeep'; @@ -274,32 +274,31 @@ export const modelsSlice = createSlice({ { payload, }: PayloadAction<{ - modelsToUpdate: ModelUpdatedValues[]; + reference: string; + updatedValues: Partial; }>, ) => { - payload.modelsToUpdate.forEach((modelToUpdate) => { - const model = state.modelsMap[modelToUpdate.reference]; + const model = state.modelsMap[payload.reference]; - if (model) { - const updatedModel = { - ...model, - ...modelToUpdate.updatedValues, - }; - state.modelsMap[model.reference] = updatedModel; - state.modelsMap[model.id] = updatedModel; + if (model) { + const updatedModel = { + ...model, + ...payload.updatedValues, + }; + state.modelsMap[model.reference] = updatedModel; + state.modelsMap[model.id] = updatedModel; - state.models = state.models.map((modelFromState) => { - if (modelFromState.reference === modelToUpdate.reference) { - return { - ...modelFromState, - ...modelToUpdate.updatedValues, - }; - } + state.models = state.models.map((model) => { + if (model.reference === payload.reference) { + return { + ...model, + ...payload.updatedValues, + }; + } - return modelFromState; - }); - } - }); + return model; + }); + } }, }, }); diff --git a/apps/chat/src/store/models/models.types.ts b/apps/chat/src/store/models/models.types.ts index f82ce8e67..4ee7761ed 100644 --- a/apps/chat/src/store/models/models.types.ts +++ b/apps/chat/src/store/models/models.types.ts @@ -1,4 +1,3 @@ -import { ApplicationInfo } from '@/src/types/applications'; import { ErrorMessage } from '@/src/types/error'; import { DialAIEntityModel, @@ -22,8 +21,3 @@ export interface ModelsState { publishRequestModels: PublishRequestDialAIEntityModel[]; publishedApplicationIds: string[]; } - -export interface ModelUpdatedValues { - reference: string; - updatedValues: Partial; -} diff --git a/apps/chat/src/store/publication/publication.epics.ts b/apps/chat/src/store/publication/publication.epics.ts index bd9450ceb..2b357e09b 100644 --- a/apps/chat/src/store/publication/publication.epics.ts +++ b/apps/chat/src/store/publication/publication.epics.ts @@ -34,8 +34,6 @@ import { splitEntityId, } from '@/src/utils/app/folders'; import { - getConversationRootId, - getPromptRootId, isApplicationId, isConversationId, isFileId, @@ -43,13 +41,14 @@ import { isRootId, } from '@/src/utils/app/id'; import { + getItemsIdsToRemoveAndHide, isEntityIdPublic, mapPublishedItems, } from '@/src/utils/app/publications'; import { translate } from '@/src/utils/app/translation'; import { ApiUtils, - getPublicItemIdWithoutVersion, + getIdWithoutVersionFromApiKey, parseConversationApiKey, parsePromptApiKey, } from '@/src/utils/server/api'; @@ -62,7 +61,6 @@ import { AppEpic } from '@/src/types/store'; import { DEFAULT_CONVERSATION_NAME } from '@/src/constants/default-ui-settings'; import { errorsMessages } from '@/src/constants/errors'; -import { NA_VERSION, PUBLIC_URL_PREFIX } from '@/src/constants/public'; import { AuthSelectors } from '../auth/auth.reducers'; import { @@ -782,7 +780,6 @@ const approvePublicationEpic: AppEpic = (action$, state$) => switchMap(({ payload }) => PublicationService.approvePublication(payload.url).pipe( switchMap(() => { - const actions: Observable[] = []; const selectedPublication = PublicationSelectors.selectSelectedPublication(state$.value); @@ -790,50 +787,60 @@ const approvePublicationEpic: AppEpic = (action$, state$) => return of(PublicationActions.approvePublicationFail()); } + const actions: Observable[] = []; + const state = state$.value; + + const resourcesToReview = + PublicationSelectors.selectResourcesToReview(state); + const conversationResources = selectedPublication.resources.filter( - (r) => isConversationId(r.targetUrl), + (resource) => isConversationId(resource.targetUrl), ); const conversationResourcesToPublish = conversationResources.filter( - (r) => r.action === PublishActions.ADD, + (resource) => resource.action === PublishActions.ADD, ); const conversationResourcesToUnpublish = conversationResources.filter( - (r) => r.action === PublishActions.DELETE, + (resource) => resource.action === PublishActions.DELETE, ); if (conversationResourcesToUnpublish.length) { - const allConversations = ConversationsSelectors.selectConversations( - state$.value, - ); - const allFolders = ConversationsSelectors.selectFolders( - state$.value, - ); - const conversationsToRemove = conversationResourcesToUnpublish.map( - (r) => r.reviewUrl, - ); + const allConversations = + ConversationsSelectors.selectConversations(state); + const allFolders = ConversationsSelectors.selectFolders(state); + + const { itemsToHideIds, itemsToRemoveIds } = + getItemsIdsToRemoveAndHide( + conversationResourcesToUnpublish, + resourcesToReview, + ); + const idsToExclude = [...itemsToRemoveIds, ...itemsToHideIds]; const filteredConversations = allConversations.filter( - (c) => !conversationsToRemove.includes(c.id), + (conv) => !idsToExclude.includes(conv.id), ); - const filteredFolders = allFolders.filter( - (f) => - f.status !== UploadStatus.LOADED || - !f.id.startsWith(getConversationRootId(PUBLIC_URL_PREFIX)) || - (filteredConversations.some((c) => - c.id.startsWith(`${f.id}/`), - ) && - f.id.startsWith(getConversationRootId(PUBLIC_URL_PREFIX))), - ); - const versionGroups = uniq( - conversationsToRemove.map((id) => { - const parsedApiKey = parseConversationApiKey( - splitEntityId(id).name, - { parseVersion: true }, - ); + const filteredFolders = allFolders.filter((folder) => { + const isNotLoaded = folder.status !== UploadStatus.LOADED; + const isPublic = !isEntityIdPublic(folder); + const hasConversations = filteredConversations.some((conv) => + conv.id.startsWith(`${folder.id}/`), + ); - return getPublicItemIdWithoutVersion( - parsedApiKey.publicationInfo?.version ?? NA_VERSION, - id, - ); - }), + return isNotLoaded || isPublic || hasConversations; + }); + const foldersToHide = allFolders.filter((folder) => { + const hasConversations = filteredConversations.some((conv) => + conv.id.startsWith(`${folder.id}/`), + ); + const hasHiddenConversations = itemsToHideIds.some((convId) => + convId.startsWith(`${folder.id}/`), + ); + + return !hasConversations && hasHiddenConversations; + }); + + const versionGroups = uniq( + itemsToRemoveIds.map((id) => + getIdWithoutVersionFromApiKey(id, parseConversationApiKey), + ), ); actions.push( @@ -842,27 +849,51 @@ const approvePublicationEpic: AppEpic = (action$, state$) => conversations: filteredConversations, }), ), + of( + ConversationsActions.addConversations({ + conversations: allConversations + .filter((conv) => itemsToHideIds.includes(conv.id)) + .map((conv) => ({ + status: undefined, + id: conv.id, + model: { id: conv.model.id }, + name: conv.name, + folderId: conv.folderId, + publicationInfo: { + isNotExist: true, + }, + publishedWithMe: false, + })), + }), + ), of( ConversationsActions.setFolders({ folders: filteredFolders, }), ), + of( + ConversationsActions.addFolders({ + folders: foldersToHide.map((folder) => ({ + ...folder, + publishedWithMe: false, + })), + }), + ), + of( + PublicationActions.markResourcesAsReviewedByIds({ + ids: itemsToHideIds, + }), + ), of( PublicationActions.removePublicVersionGroups({ groupsToRemove: versionGroups.map((groupId) => ({ - groupIds: conversationsToRemove.filter((id) => { - const parsedApiKey = parseConversationApiKey( - splitEntityId(id).name, - { parseVersion: true }, - ); - - return ( - getPublicItemIdWithoutVersion( - parsedApiKey.publicationInfo?.version ?? NA_VERSION, + groupIds: idsToExclude.filter( + (id) => + getIdWithoutVersionFromApiKey( id, - ) === groupId - ); - }), + parseConversationApiKey, + ) === groupId, + ), versionGroupId: groupId, })), }), @@ -875,7 +906,7 @@ const approvePublicationEpic: AppEpic = (action$, state$) => conversationResourcesToPublish.flatMap((resource) => getParentFolderIdsFromEntityId( getFolderIdFromEntityId(resource.targetUrl), - ).filter((p) => p !== resource.targetUrl), + ).filter((folderId) => folderId !== resource.targetUrl), ), ); @@ -900,7 +931,13 @@ const approvePublicationEpic: AppEpic = (action$, state$) => ), of( ConversationsActions.addConversations({ - conversations: items, + conversations: items.map((item) => { + if (item.publicationInfo?.isNotExist) { + item.publicationInfo.isNotExist = false; + } + + return item; + }), }), ), of( @@ -911,42 +948,50 @@ const approvePublicationEpic: AppEpic = (action$, state$) => ); } - const promptResources = selectedPublication.resources.filter((r) => - isPromptId(r.targetUrl), + const promptResources = selectedPublication.resources.filter( + (resource) => isPromptId(resource.targetUrl), ); const promptResourcesToPublish = promptResources.filter( - (r) => r.action === PublishActions.ADD, + (resource) => resource.action === PublishActions.ADD, ); const promptResourcesToUnpublish = promptResources.filter( - (r) => r.action === PublishActions.DELETE, + (resource) => resource.action === PublishActions.DELETE, ); if (promptResourcesToUnpublish.length) { - const allPrompts = PromptsSelectors.selectPrompts(state$.value); - const promptsToRemove = promptResourcesToUnpublish.map( - (r) => r.reviewUrl, - ); - const allFolders = PromptsSelectors.selectFolders(state$.value); + const allPrompts = PromptsSelectors.selectPrompts(state); + const allFolders = PromptsSelectors.selectFolders(state); + const { itemsToHideIds, itemsToRemoveIds } = + getItemsIdsToRemoveAndHide( + promptResourcesToUnpublish, + resourcesToReview, + ); + const idsToExclude = [...itemsToRemoveIds, ...itemsToHideIds]; const filteredPrompts = allPrompts.filter( - (p) => !promptsToRemove.includes(p.id), - ); - const filteredFolders = allFolders.filter( - (f) => - f.status !== UploadStatus.LOADED || - !f.id.startsWith(getPromptRootId(PUBLIC_URL_PREFIX)) || - (filteredPrompts.some((c) => c.id.startsWith(`${f.id}/`)) && - f.id.startsWith(getPromptRootId(PUBLIC_URL_PREFIX))), + (prompt) => !idsToExclude.includes(prompt.id), ); + const filteredFolders = allFolders.filter((folder) => { + const isNotLoaded = folder.status !== UploadStatus.LOADED; + const isPublic = !isEntityIdPublic(folder); + const hasPrompts = filteredPrompts.some((prompt) => + prompt.id.startsWith(`${folder.id}/`), + ); + + return isNotLoaded || isPublic || hasPrompts; + }); + const foldersToHide = allFolders.filter((folder) => { + const hasPrompts = filteredPrompts.some((prompt) => + prompt.id.startsWith(`${folder.id}/`), + ); + const hasHiddenPrompts = itemsToHideIds.some((promptId) => + promptId.startsWith(`${folder.id}/`), + ); + + return !hasPrompts && hasHiddenPrompts; + }); const versionGroups = uniq( - promptsToRemove.map((id) => { - const parsedApiKey = parsePromptApiKey(splitEntityId(id).name, { - parseVersion: true, - }); - - return getPublicItemIdWithoutVersion( - parsedApiKey.publicationInfo?.version ?? NA_VERSION, - id, - ); + itemsToRemoveIds.map((id) => { + return getIdWithoutVersionFromApiKey(id, parsePromptApiKey); }), ); @@ -956,25 +1001,47 @@ const approvePublicationEpic: AppEpic = (action$, state$) => prompts: filteredPrompts, }), ), + of( + PromptsActions.addPrompts({ + prompts: allPrompts + .filter((prompt) => itemsToHideIds.includes(prompt.id)) + .map((prompt) => ({ + status: undefined, + id: prompt.id, + name: prompt.name, + folderId: prompt.folderId, + publicationInfo: { + isNotExist: true, + }, + publishedWithMe: false, + })), + }), + ), of( PromptsActions.setFolders({ folders: filteredFolders, }), ), + of( + PromptsActions.addFolders({ + folders: foldersToHide.map((folder) => ({ + ...folder, + publishedWithMe: false, + })), + }), + ), + of( + PublicationActions.markResourcesAsReviewedByIds({ + ids: itemsToHideIds, + }), + ), of( PublicationActions.removePublicVersionGroups({ groupsToRemove: versionGroups.map((groupId) => ({ - groupIds: promptsToRemove.filter((id) => { - const parsedApiKey = parseConversationApiKey( - splitEntityId(id).name, - { parseVersion: true }, - ); - + groupIds: idsToExclude.filter((id) => { return ( - getPublicItemIdWithoutVersion( - parsedApiKey.publicationInfo?.version ?? NA_VERSION, - id, - ) === groupId + getIdWithoutVersionFromApiKey(id, parsePromptApiKey) === + groupId ); }), versionGroupId: groupId, @@ -989,7 +1056,7 @@ const approvePublicationEpic: AppEpic = (action$, state$) => promptResourcesToPublish.flatMap((resource) => getParentFolderIdsFromEntityId( getFolderIdFromEntityId(resource.targetUrl), - ).filter((p) => p !== resource.targetUrl), + ).filter((folderId) => folderId !== resource.targetUrl), ), ); @@ -1013,7 +1080,13 @@ const approvePublicationEpic: AppEpic = (action$, state$) => ), of( PromptsActions.addPrompts({ - prompts: items, + prompts: items.map((item) => { + if (item.publicationInfo?.isNotExist) { + item.publicationInfo.isNotExist = false; + } + + return item; + }), }), ), of( diff --git a/apps/chat/src/store/publication/publication.reducers.ts b/apps/chat/src/store/publication/publication.reducers.ts index 3a8970059..04c090223 100644 --- a/apps/chat/src/store/publication/publication.reducers.ts +++ b/apps/chat/src/store/publication/publication.reducers.ts @@ -163,6 +163,20 @@ export const publicationSlice = createSlice({ : resource, ); }, + markResourcesAsReviewedByIds: ( + state, + { + payload, + }: PayloadAction<{ + ids: string[]; + }>, + ) => { + state.resourcesToReview = state.resourcesToReview.map((resource) => + payload.ids.includes(resource.reviewUrl) + ? { ...resource, reviewed: true } + : resource, + ); + }, uploadRules: (state, _action: PayloadAction<{ path: string }>) => { state.isRulesLoading = true; }, diff --git a/apps/chat/src/store/share/share.epics.ts b/apps/chat/src/store/share/share.epics.ts index b174f90b0..aa72f2c9a 100644 --- a/apps/chat/src/store/share/share.epics.ts +++ b/apps/chat/src/store/share/share.epics.ts @@ -16,7 +16,6 @@ import { AnyAction } from '@reduxjs/toolkit'; import { combineEpics } from 'redux-observable'; -import { getApplicationType } from '@/src/utils/app/application'; import { ConversationService } from '@/src/utils/app/data/conversation-service'; import { ShareService } from '@/src/utils/app/data/share-service'; import { @@ -36,7 +35,6 @@ import { hasWritePermission } from '@/src/utils/app/share'; import { translate } from '@/src/utils/app/translation'; import { ApiUtils, parseConversationApiKey } from '@/src/utils/server/api'; -import { ApplicationType } from '@/src/types/applications'; import { Conversation } from '@/src/types/chat'; import { FeatureType } from '@/src/types/common'; import { DialFile } from '@/src/types/files'; @@ -54,10 +52,7 @@ import { DEFAULT_CONVERSATION_NAME } from '@/src/constants/default-ui-settings'; import { errorsMessages } from '@/src/constants/errors'; import { DeleteType } from '@/src/constants/marketplace'; -import { - ApplicationActions, - ApplicationSelectors, -} from '../application/application.reducers'; +import { ApplicationSelectors } from '../application/application.reducers'; import { ConversationsActions, ConversationsSelectors, @@ -65,7 +60,6 @@ import { import { FilesActions, FilesSelectors } from '../files/files.reducers'; import { MarketplaceActions } from '../marketplace/marketplace.reducers'; import { ModelsActions, ModelsSelectors } from '../models/models.reducers'; -import { ModelUpdatedValues } from '../models/models.types'; import { PromptsActions, PromptsSelectors } from '../prompts/prompts.reducers'; import { SettingsSelectors } from '../settings/settings.reducers'; import { UIActions } from '../ui/ui.reducers'; @@ -299,30 +293,6 @@ const shareApplicationEpic: AppEpic = (action$, state$) => action$.pipe( filter(ShareActions.shareApplication.match), switchMap(({ payload }) => { - const modelsMap = ModelsSelectors.selectModelsMap(state$.value); - const application = modelsMap[payload.resourceId]; - - if (!application) { - return of(ShareActions.shareFail()); - } - - const applicationType = getApplicationType(application); - const applicationDetails = ApplicationSelectors.selectApplicationDetail( - state$.value, - ); - - if ( - applicationType === ApplicationType.CODE_APP && - applicationDetails?.reference !== application.reference - ) { - return of( - ApplicationActions.get({ - applicationId: payload.resourceId, - isForSharing: true, - }), - ); - } - const resources: ShareResource[] = [ { url: ApiUtils.encodeApiUrl(payload.resourceId), @@ -330,15 +300,18 @@ const shareApplicationEpic: AppEpic = (action$, state$) => }, ]; - if (application?.iconUrl) { + const applicationDetails = ApplicationSelectors.selectApplicationDetail( + state$.value, + ); + + if (applicationDetails?.iconUrl) { resources.push({ - url: ApiUtils.encodeApiUrl(application.iconUrl), + url: ApiUtils.encodeApiUrl(applicationDetails.iconUrl), }); } if ( hasWritePermission(payload.permissions) && - applicationType && applicationDetails?.function?.sourceFolder ) { resources.push({ @@ -906,72 +879,50 @@ const getSharedListingSuccessEpic: AppEpic = (action$, state$) => if (payload.featureType === FeatureType.Application) { const modelsMap = ModelsSelectors.selectModelsMap(state$.value); if (payload.sharedWith === ShareRelations.others) { - const modelsToUpdate = payload.resources.entities - .map((sharedItem) => { - const sharedModel = modelsMap[sharedItem.id]; - - if (sharedModel) { - return { - reference: sharedModel.reference, - updatedValues: { - isShared: true, - }, - }; - } - return undefined; - }) - .filter(Boolean) as ModelUpdatedValues[]; - - actions.push(ModelsActions.updateLocalModels({ modelsToUpdate })); + actions.push( + ...(payload.resources.entities + .map((sharedItem) => { + const sharedModel = modelsMap[sharedItem.id]; + + if (sharedModel) { + return ModelsActions.updateLocalModels({ + reference: sharedModel.reference, + updatedValues: { + isShared: true, + }, + }); + } + return undefined; + }) + .filter(Boolean) as AnyAction[]), + ); } else { //TODO make request for the shared applications to add them into the state when share invitation is accepted. //TODO new action-service needs to be created. + //TODO add all shared with me agents to installedModels - const updateSharedActions: AnyAction[] = []; - const modelsToUpdate = payload.resources.entities - .map((sharedItem) => { - const sharedModel = modelsMap[sharedItem.id]; - - if (sharedModel) { - return { - reference: sharedModel.reference, - updatedValues: { - sharedWithMe: true, - permissions: sharedItem.permissions, - }, - }; - } - return undefined; - }) - .filter(Boolean) as ModelUpdatedValues[]; - - if (modelsToUpdate.length) { - updateSharedActions.push( - ModelsActions.updateLocalModels({ modelsToUpdate }), - ); - - updateSharedActions.push(ModelsActions.getInstalledModelIds()); - - const { acceptedId } = ShareSelectors.selectAcceptedEntityInfo( - state$.value, - ); + // const sharedReferences: string[] = []; //part of TODO uncomment or remove if not needed; - const acceptedApplicationReference = - acceptedId && modelsMap[acceptedId]?.reference; + actions.push( + ...(payload.resources.entities + .map((sharedItem) => { + const sharedModel = modelsMap[sharedItem.id]; - if (acceptedApplicationReference) { - updateSharedActions.push( - MarketplaceActions.setDetailsModel({ - reference: acceptedApplicationReference, - isSuggested: false, - }), - ); - } + if (sharedModel) { + // sharedReferences.push(sharedModel.reference); //part of TODO uncomment or remove if not needed; - actions.push(...updateSharedActions); - } - - actions.push(ShareActions.resetAcceptedEntityInfo()); + return ModelsActions.updateLocalModels({ + reference: sharedModel.reference, + updatedValues: { + sharedWithMe: true, + permissions: sharedItem.permissions, + }, + }); + } + return undefined; + }) + .filter(Boolean) as AnyAction[]), + ); } } @@ -1059,14 +1010,10 @@ const revokeAccessSuccessEpic: AppEpic = (action$, state$) => } return of( ModelsActions.updateLocalModels({ - modelsToUpdate: [ - { - reference: applicationReference, - updatedValues: { - isShared: false, - }, - }, - ], + reference: applicationReference, + updatedValues: { + isShared: false, + }, }), ); } diff --git a/apps/chat/src/store/share/share.reducers.ts b/apps/chat/src/store/share/share.reducers.ts index b6b6d997c..00bcc9ddf 100644 --- a/apps/chat/src/store/share/share.reducers.ts +++ b/apps/chat/src/store/share/share.reducers.ts @@ -1,4 +1,4 @@ -import { PayloadAction, createSlice } from '@reduxjs/toolkit'; +import { PayloadAction, createSelector, createSlice } from '@reduxjs/toolkit'; import { splitEntityId } from '@/src/utils/app/folders'; import { hasWritePermission } from '@/src/utils/app/share'; @@ -9,14 +9,14 @@ import { import { ApplicationInfo } from '@/src/types/applications'; import { FeatureType } from '@/src/types/common'; +import { ErrorMessage } from '@/src/types/error'; import { DialFile } from '@/src/types/files'; import { FolderInterface } from '@/src/types/folder'; import { ModalState } from '@/src/types/modal'; import { Prompt } from '@/src/types/prompt'; import { ShareRelations } from '@/src/types/share'; -import * as ShareSelectors from './share.selectors'; -import { ShareState } from './share.types'; +import { RootState } from '../index'; import { ConversationInfo, @@ -25,7 +25,23 @@ import { UploadStatus, } from '@epam/ai-dial-shared'; -export { ShareSelectors }; +export interface ShareState { + initialized: boolean; + status: UploadStatus; + error: ErrorMessage | undefined; + invitationId: string | undefined; + writeInvitationId: string | undefined; + shareResourceName: string | undefined; + shareResourceId: string | undefined; + shareModalState: ModalState; + unshareEntity?: Omit; + acceptedId: string | undefined; + isFolderAccepted: boolean | undefined; + shareFeatureType?: FeatureType; + shareIsFolder?: boolean; + isConversation?: boolean; + isPrompt?: boolean; +} const initialState: ShareState = { initialized: false, @@ -70,7 +86,6 @@ export const shareSlice = createSlice({ state.shareFeatureType = payload.featureType; state.shareIsFolder = payload.isFolder; state.shareResourceId = payload.resourceId; - state.sharePermissions = payload.permissions; const name = splitEntityId(payload.resourceId).name; state.shareResourceName = @@ -106,16 +121,12 @@ export const shareSlice = createSlice({ ) => state, shareApplication: ( state, - { - payload, - }: PayloadAction<{ + _action: PayloadAction<{ resourceId: string; permissions?: SharePermission[]; }>, ) => { state.shareModalState = ModalState.LOADING; - state.sharePermissions = payload.permissions; - state.shareResourceId = payload.resourceId; }, shareSuccess: ( state, @@ -133,12 +144,10 @@ export const shareSlice = createSlice({ } state.shareModalState = ModalState.OPENED; - state.sharePermissions = undefined; }, shareFail: (state, _action: PayloadAction) => { state.invitationId = undefined; state.shareModalState = ModalState.CLOSED; - state.sharePermissions = undefined; }, revokeAccess: ( @@ -257,4 +266,67 @@ export const shareSlice = createSlice({ }, }); +const rootSelector = (state: RootState): ShareState => state.share; + +const selectInvitationId = createSelector([rootSelector], (state) => { + return state.invitationId; +}); + +const selectWriteInvitationId = createSelector([rootSelector], (state) => { + return state.writeInvitationId; +}); + +const selectShareModalState = createSelector([rootSelector], (state) => { + return state.shareModalState; +}); + +const selectShareModalClosed = createSelector([rootSelector], (state) => { + return state.shareModalState === ModalState.CLOSED; +}); + +const selectUnshareModel = createSelector([rootSelector], (state) => { + return state.unshareEntity; +}); + +const selectShareResourceId = createSelector([rootSelector], (state) => { + return state.shareResourceId; +}); + +const selectShareResourceName = createSelector([rootSelector], (state) => { + return state.shareResourceName; +}); + +const selectShareFeatureType = createSelector([rootSelector], (state) => { + return state.shareFeatureType; +}); +const selectShareIsFolder = createSelector([rootSelector], (state) => { + return state.shareIsFolder; +}); +const selectAcceptedEntityInfo = createSelector([rootSelector], (state) => { + return { + acceptedId: state.acceptedId, + isFolderAccepted: state.isFolderAccepted, + isConversation: state.isConversation, + isPrompt: state.isPrompt, + }; +}); +const selectInitialized = createSelector( + [rootSelector], + (state) => state.initialized, +); + +export const ShareSelectors = { + selectInvitationId, + selectWriteInvitationId, + selectShareModalState, + selectShareModalClosed, + selectUnshareModel, + selectShareResourceName, + selectShareResourceId, + selectAcceptedEntityInfo, + selectShareFeatureType, + selectShareIsFolder, + selectInitialized, +}; + export const ShareActions = shareSlice.actions; diff --git a/apps/chat/src/store/share/share.selectors.ts b/apps/chat/src/store/share/share.selectors.ts deleted file mode 100644 index 7a5b96110..000000000 --- a/apps/chat/src/store/share/share.selectors.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { createSelector } from '@reduxjs/toolkit'; - -import { ModalState } from '@/src/types/modal'; - -import { RootState } from '..'; -import { ShareState } from './share.types'; - -const rootSelector = (state: RootState): ShareState => state.share; - -export const selectInvitationId = createSelector([rootSelector], (state) => { - return state.invitationId; -}); - -export const selectWriteInvitationId = createSelector( - [rootSelector], - (state) => { - return state.writeInvitationId; - }, -); - -export const selectShareModalState = createSelector([rootSelector], (state) => { - return state.shareModalState; -}); -export const selectShareModalClosed = createSelector( - [rootSelector], - (state) => { - return state.shareModalState === ModalState.CLOSED; - }, -); - -export const selectShareResourceId = createSelector([rootSelector], (state) => { - return state.shareResourceId; -}); - -export const selectShareResourceName = createSelector( - [rootSelector], - (state) => { - return state.shareResourceName; - }, -); - -export const selectShareFeatureType = createSelector( - [rootSelector], - (state) => { - return state.shareFeatureType; - }, -); -export const selectShareIsFolder = createSelector([rootSelector], (state) => { - return state.shareIsFolder; -}); -export const selectAcceptedEntityInfo = createSelector( - [rootSelector], - (state) => { - return { - acceptedId: state.acceptedId, - isFolderAccepted: state.isFolderAccepted, - isConversation: state.isConversation, - isPrompt: state.isPrompt, - }; - }, -); -export const selectInitialized = createSelector( - [rootSelector], - (state) => state.initialized, -); -export const selectSharePermissions = createSelector( - [rootSelector], - (state) => state.sharePermissions, -); -export const selectUnshareModel = createSelector([rootSelector], (state) => { - return state.unshareEntity; -}); diff --git a/apps/chat/src/store/share/share.types.ts b/apps/chat/src/store/share/share.types.ts deleted file mode 100644 index eaa2e650b..000000000 --- a/apps/chat/src/store/share/share.types.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { FeatureType } from '@/src/types/common'; -import { ErrorMessage } from '@/src/types/error'; -import { ModalState } from '@/src/types/modal'; - -import { - ShareEntity, - SharePermission, - UploadStatus, -} from '@epam/ai-dial-shared'; - -export interface ShareState { - initialized: boolean; - status: UploadStatus; - error: ErrorMessage | undefined; - invitationId: string | undefined; - writeInvitationId: string | undefined; - shareResourceName: string | undefined; - shareResourceId: string | undefined; - shareModalState: ModalState; - unshareEntity?: Omit; - acceptedId: string | undefined; - isFolderAccepted: boolean | undefined; - shareFeatureType?: FeatureType; - shareIsFolder?: boolean; - isConversation?: boolean; - isPrompt?: boolean; - sharePermissions?: SharePermission[]; -} diff --git a/apps/chat/src/types/applications.ts b/apps/chat/src/types/applications.ts index eb40e6764..326e198c6 100644 --- a/apps/chat/src/types/applications.ts +++ b/apps/chat/src/types/applications.ts @@ -125,4 +125,5 @@ export enum ApplicationType { CUSTOM_APP = 'application', QUICK_APP = 'quick app', CODE_APP = 'code app', + MINDMAP = 'mindmap', } diff --git a/apps/chat/src/utils/app/application.ts b/apps/chat/src/utils/app/application.ts index 65072e179..ca9b327bc 100644 --- a/apps/chat/src/utils/app/application.ts +++ b/apps/chat/src/utils/app/application.ts @@ -181,7 +181,7 @@ export const isExecutableApp = (entity: DialAIEntityModel) => export const getApplicationType = (entity: DialAIEntityModel) => { if (isQuickApp(entity)) return ApplicationType.QUICK_APP; if (isExecutableApp(entity)) return ApplicationType.CODE_APP; - + // TODO: Add mindmap type check in future return ApplicationType.CUSTOM_APP; }; diff --git a/apps/chat/src/utils/app/publications.ts b/apps/chat/src/utils/app/publications.ts index bcbaec46c..f2834d42c 100644 --- a/apps/chat/src/utils/app/publications.ts +++ b/apps/chat/src/utils/app/publications.ts @@ -1,6 +1,10 @@ import { FeatureType } from '@/src/types/common'; import { PromptInfo } from '@/src/types/prompt'; -import { PublicVersionGroups } from '@/src/types/publication'; +import { + PublicVersionGroups, + PublicationResource, + ResourceToReview, +} from '@/src/types/publication'; import { SharingType } from '@/src/types/share'; import { @@ -170,3 +174,34 @@ export const mapPublishedItems = ( export const getPublicationId = (url: string) => url.split('/').slice(-1).shift(); + +export const getItemsIdsToRemoveAndHide = ( + allResources: PublicationResource[], + resourcesToReview: ResourceToReview[], +) => { + const itemsToHide: PublicationResource[] = []; + const itemsToRemove: PublicationResource[] = []; + + const reviewUrlCountMap = resourcesToReview.reduce>( + (acc, res) => { + acc[res.reviewUrl] = (acc[res.reviewUrl] || 0) + 1; + return acc; + }, + {}, + ); + + allResources.forEach((resource) => { + const count = reviewUrlCountMap[resource.reviewUrl] || 0; + + if (count > 1) { + itemsToHide.push(resource); + } else { + itemsToRemove.push(resource); + } + }); + + return { + itemsToHideIds: itemsToHide.map((item) => item.reviewUrl), + itemsToRemoveIds: itemsToRemove.map((item) => item.reviewUrl), + }; +}; diff --git a/apps/chat/src/utils/marketplace.ts b/apps/chat/src/utils/marketplace.ts index 57c79e7cf..4da93911f 100644 --- a/apps/chat/src/utils/marketplace.ts +++ b/apps/chat/src/utils/marketplace.ts @@ -1,7 +1,6 @@ import { + getApplicationType, isApplicationPublic, - isExecutableApp, - isQuickApp, } from '@/src/utils/app/application'; import { isMyApplication } from '@/src/utils/app/id'; import { doesEntityContainSearchTerm } from '@/src/utils/app/search'; @@ -9,7 +8,11 @@ import { doesEntityContainSearchTerm } from '@/src/utils/app/search'; import { MarketplaceFilters } from '@/src/types/marketplace'; import { DialAIEntityModel } from '@/src/types/models'; -import { FilterTypes, SourceType } from '@/src/constants/marketplace'; +import { + ApplicationTypeToSourceType, + FilterTypes, + SourceType, +} from '@/src/constants/marketplace'; import intersection from 'lodash-es/intersection'; @@ -44,19 +47,12 @@ export const doesApplicationMatchFilters = ( if (selectedFilters[FilterTypes.SOURCES].length) { const sources = selectedFilters[FilterTypes.SOURCES]; + const applicationType = getApplicationType(model); if ( (sources.includes(SourceType.Public) && isApplicationPublic(model)) || (sources.includes(SourceType.SharedWithMe) && model.sharedWithMe) || - (sources.includes(SourceType.MyQuickApps) && - isMyApplication(model) && - isQuickApp(model)) || - (sources.includes(SourceType.MyCodeApps) && - isMyApplication(model) && - isExecutableApp(model)) || - (sources.includes(SourceType.MyCustomApps) && - isMyApplication(model) && - !isExecutableApp(model) && - !isQuickApp(model)) + (isMyApplication(model) && + sources.includes(ApplicationTypeToSourceType[applicationType])) ) { return true; } diff --git a/apps/chat/src/utils/server/api.ts b/apps/chat/src/utils/server/api.ts index 02e68f52d..acbf8df84 100644 --- a/apps/chat/src/utils/server/api.ts +++ b/apps/chat/src/utils/server/api.ts @@ -14,6 +14,7 @@ import { NA_VERSION } from '@/src/constants/public'; import { validVersionRegEx } from '@/src/constants/versions'; import { constructPath } from '../app/file'; +import { splitEntityId } from '../app/folders'; import { ConversationInfo } from '@epam/ai-dial-shared'; @@ -291,3 +292,20 @@ export const isValidEntityApiType = (apiKey: string): boolean => { Object.values(CoreApiKeys).includes(apiKey as CoreApiKeys) ); }; + +export const getIdWithoutVersionFromApiKey = ( + id: string, + parseMethod: + | typeof parseApplicationApiKey + | typeof parseConversationApiKey + | typeof parsePromptApiKey, +) => { + const parsedApiKey = parseMethod(splitEntityId(id).name, { + parseVersion: true, + }); + + return getPublicItemIdWithoutVersion( + parsedApiKey.publicationInfo?.version ?? NA_VERSION, + id, + ); +}; diff --git a/package.json b/package.json index 54bdf7a79..2ef5153da 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.24.0-rc", "private": true, "scripts": { - "nx": "NODE_OPTIONS='--max-http-header-size=32768' nx", + "nx": "nx", "postinstall": "patch-package && node tools/patch-nextjs.js", "graph": "nx graph", "build": "nx run-many -t build",