feat: frontend part of support try apps (#31287)

Co-authored-by: CodingOnStar <hanxujiang@dify.ai>
Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
This commit is contained in:
Joel
2026-01-22 18:16:37 +08:00
committed by GitHub
parent c575c34ca6
commit b9f718005c
130 changed files with 3233 additions and 685 deletions
+1 -19
View File
@@ -1,4 +1,4 @@
import type { IOnCompleted, IOnData, IOnError, IOnFile, IOnMessageEnd, IOnMessageReplace, IOnThought } from './base'
import type { IOnCompleted, IOnData, IOnError, IOnMessageReplace } from './base'
import type { ModelParameterRule } from '@/app/components/header/account-setting/model-provider-page/declarations'
import type { ChatPromptConfig, CompletionPromptConfig } from '@/models/debug'
import type { AppModeEnum, ModelModeType } from '@/types/app'
@@ -25,24 +25,6 @@ export type CodeGenRes = {
error?: string
}
export const sendChatMessage = async (appId: string, body: Record<string, any>, { onData, onCompleted, onThought, onFile, onError, getAbortController, onMessageEnd, onMessageReplace }: {
onData: IOnData
onCompleted: IOnCompleted
onFile: IOnFile
onThought: IOnThought
onMessageEnd: IOnMessageEnd
onMessageReplace: IOnMessageReplace
onError: IOnError
getAbortController?: (abortController: AbortController) => void
}) => {
return ssePost(`apps/${appId}/chat-messages`, {
body: {
...body,
response_mode: 'streaming',
},
}, { onData, onCompleted, onThought, onFile, onError, getAbortController, onMessageEnd, onMessageReplace })
}
export const stopChatMessageResponding = async (appId: string, taskId: string) => {
return post(`apps/${appId}/chat-messages/${taskId}/stop`)
}
+7
View File
@@ -1,4 +1,5 @@
import type { AccessMode } from '@/models/access-control'
import type { Banner } from '@/models/app'
import type { App, AppCategory } from '@/models/explore'
import { del, get, patch } from './base'
@@ -9,6 +10,7 @@ export const fetchAppList = () => {
}>('/explore/apps')
}
// eslint-disable-next-line ts/no-explicit-any
export const fetchAppDetail = (id: string): Promise<any> => {
return get(`/explore/apps/${id}`)
}
@@ -32,3 +34,8 @@ export const updatePinStatus = (id: string, isPinned: boolean) => {
export const getAppAccessModeByAppId = (appId: string) => {
return get<{ accessMode: AccessMode }>(`/enterprise/webapp/app/access-mode?appId=${appId}`)
}
export const fetchBanners = (language?: string): Promise<Banner[]> => {
const url = language ? `/explore/banners?language=${language}` : '/explore/banners'
return get<Banner[]>(url)
}
+80 -85
View File
@@ -2,22 +2,17 @@ import type {
IOnCompleted,
IOnData,
IOnError,
IOnFile,
IOnIterationFinished,
IOnIterationNext,
IOnIterationStarted,
IOnLoopFinished,
IOnLoopNext,
IOnLoopStarted,
IOnMessageEnd,
IOnMessageReplace,
IOnNodeFinished,
IOnNodeStarted,
IOnTextChunk,
IOnTextReplace,
IOnThought,
IOnTTSChunk,
IOnTTSEnd,
IOnWorkflowFinished,
IOnWorkflowStarted,
} from './base'
@@ -44,45 +39,43 @@ import {
} from './base'
import { getWebAppAccessToken } from './webapp-auth'
function getAction(action: 'get' | 'post' | 'del' | 'patch', isInstalledApp: boolean) {
export enum AppSourceType {
webApp = 'webApp',
installedApp = 'installedApp',
tryApp = 'tryApp',
}
const apiPrefix = {
[AppSourceType.webApp]: '',
[AppSourceType.installedApp]: 'installed-apps',
[AppSourceType.tryApp]: 'trial-apps',
}
function getIsPublicAPI(appSourceType: AppSourceType) {
return appSourceType === AppSourceType.webApp
}
function getAction(action: 'get' | 'post' | 'del' | 'patch', appSourceType: AppSourceType) {
const isNeedLogin = !getIsPublicAPI(appSourceType)
switch (action) {
case 'get':
return isInstalledApp ? consoleGet : get
return isNeedLogin ? consoleGet : get
case 'post':
return isInstalledApp ? consolePost : post
return isNeedLogin ? consolePost : post
case 'patch':
return isInstalledApp ? consolePatch : patch
return isNeedLogin ? consolePatch : patch
case 'del':
return isInstalledApp ? consoleDel : del
return isNeedLogin ? consoleDel : del
}
}
export function getUrl(url: string, isInstalledApp: boolean, installedAppId: string) {
return isInstalledApp ? `installed-apps/${installedAppId}/${url.startsWith('/') ? url.slice(1) : url}` : url
export function getUrl(url: string, appSourceType: AppSourceType, appId: string) {
const hasPrefix = appSourceType !== AppSourceType.webApp
return hasPrefix ? `${apiPrefix[appSourceType]}/${appId}/${url.startsWith('/') ? url.slice(1) : url}` : url
}
export const sendChatMessage = async (body: Record<string, any>, { onData, onCompleted, onThought, onFile, onError, getAbortController, onMessageEnd, onMessageReplace, onTTSChunk, onTTSEnd }: {
onData: IOnData
onCompleted: IOnCompleted
onFile: IOnFile
onThought: IOnThought
onError: IOnError
onMessageEnd?: IOnMessageEnd
onMessageReplace?: IOnMessageReplace
getAbortController?: (abortController: AbortController) => void
onTTSChunk?: IOnTTSChunk
onTTSEnd?: IOnTTSEnd
}, isInstalledApp: boolean, installedAppId = '') => {
return ssePost(getUrl('chat-messages', isInstalledApp, installedAppId), {
body: {
...body,
response_mode: 'streaming',
},
}, { onData, onCompleted, onThought, onFile, isPublicAPI: !isInstalledApp, onError, getAbortController, onMessageEnd, onMessageReplace, onTTSChunk, onTTSEnd })
}
export const stopChatMessageResponding = async (appId: string, taskId: string, isInstalledApp: boolean, installedAppId = '') => {
return getAction('post', isInstalledApp)(getUrl(`chat-messages/${taskId}/stop`, isInstalledApp, installedAppId))
export const stopChatMessageResponding = async (appId: string, taskId: string, appSourceType: AppSourceType, installedAppId = '') => {
return getAction('post', appSourceType)(getUrl(`chat-messages/${taskId}/stop`, appSourceType, installedAppId))
}
export const sendCompletionMessage = async (body: Record<string, any>, { onData, onCompleted, onError, onMessageReplace, getAbortController }: {
@@ -91,13 +84,13 @@ export const sendCompletionMessage = async (body: Record<string, any>, { onData,
onError: IOnError
onMessageReplace: IOnMessageReplace
getAbortController?: (abortController: AbortController) => void
}, isInstalledApp: boolean, installedAppId = '') => {
return ssePost(getUrl('completion-messages', isInstalledApp, installedAppId), {
}, appSourceType: AppSourceType, installedAppId = '') => {
return ssePost(getUrl('completion-messages', appSourceType, installedAppId), {
body: {
...body,
response_mode: 'streaming',
},
}, { onData, onCompleted, isPublicAPI: !isInstalledApp, onError, onMessageReplace, getAbortController })
}, { onData, onCompleted, isPublicAPI: getIsPublicAPI(appSourceType), onError, onMessageReplace, getAbortController })
}
export const sendWorkflowMessage = async (
@@ -129,10 +122,10 @@ export const sendWorkflowMessage = async (
onTextChunk: IOnTextChunk
onTextReplace: IOnTextReplace
},
isInstalledApp: boolean,
installedAppId = '',
appSourceType: AppSourceType,
appId = '',
) => {
return ssePost(getUrl('workflows/run', isInstalledApp, installedAppId), {
return ssePost(getUrl('workflows/run', appSourceType, appId), {
body: {
...body,
response_mode: 'streaming',
@@ -141,7 +134,7 @@ export const sendWorkflowMessage = async (
onNodeStarted,
onWorkflowStarted,
onWorkflowFinished,
isPublicAPI: !isInstalledApp,
isPublicAPI: getIsPublicAPI(appSourceType),
onNodeFinished,
onIterationStart,
onIterationNext,
@@ -154,42 +147,42 @@ export const sendWorkflowMessage = async (
})
}
export const stopWorkflowMessage = async (_appId: string, taskId: string, isInstalledApp: boolean, installedAppId = '') => {
export const stopWorkflowMessage = async (_appId: string, taskId: string, appSourceType: AppSourceType, installedAppId = '') => {
if (!taskId)
return
return getAction('post', isInstalledApp)(getUrl(`workflows/tasks/${taskId}/stop`, isInstalledApp, installedAppId))
return getAction('post', appSourceType)(getUrl(`workflows/tasks/${taskId}/stop`, appSourceType, installedAppId))
}
export const fetchAppInfo = async () => {
return get('/site') as Promise<AppData>
}
export const fetchConversations = async (isInstalledApp: boolean, installedAppId = '', last_id?: string, pinned?: boolean, limit?: number) => {
return getAction('get', isInstalledApp)(getUrl('conversations', isInstalledApp, installedAppId), { params: { limit: limit || 20, ...(last_id ? { last_id } : {}), ...(pinned !== undefined ? { pinned } : {}) } }) as Promise<AppConversationData>
export const fetchConversations = async (appSourceType: AppSourceType, installedAppId = '', last_id?: string, pinned?: boolean, limit?: number) => {
return getAction('get', appSourceType)(getUrl('conversations', appSourceType, installedAppId), { params: { limit: limit || 20, ...(last_id ? { last_id } : {}), ...(pinned !== undefined ? { pinned } : {}) } }) as Promise<AppConversationData>
}
export const pinConversation = async (isInstalledApp: boolean, installedAppId = '', id: string) => {
return getAction('patch', isInstalledApp)(getUrl(`conversations/${id}/pin`, isInstalledApp, installedAppId))
export const pinConversation = async (appSourceType: AppSourceType, installedAppId = '', id: string) => {
return getAction('patch', appSourceType)(getUrl(`conversations/${id}/pin`, appSourceType, installedAppId))
}
export const unpinConversation = async (isInstalledApp: boolean, installedAppId = '', id: string) => {
return getAction('patch', isInstalledApp)(getUrl(`conversations/${id}/unpin`, isInstalledApp, installedAppId))
export const unpinConversation = async (appSourceType: AppSourceType, installedAppId = '', id: string) => {
return getAction('patch', appSourceType)(getUrl(`conversations/${id}/unpin`, appSourceType, installedAppId))
}
export const delConversation = async (isInstalledApp: boolean, installedAppId = '', id: string) => {
return getAction('del', isInstalledApp)(getUrl(`conversations/${id}`, isInstalledApp, installedAppId))
export const delConversation = async (appSourceType: AppSourceType, installedAppId = '', id: string) => {
return getAction('del', appSourceType)(getUrl(`conversations/${id}`, appSourceType, installedAppId))
}
export const renameConversation = async (isInstalledApp: boolean, installedAppId = '', id: string, name: string) => {
return getAction('post', isInstalledApp)(getUrl(`conversations/${id}/name`, isInstalledApp, installedAppId), { body: { name } })
export const renameConversation = async (appSourceType: AppSourceType, installedAppId = '', id: string, name: string) => {
return getAction('post', appSourceType)(getUrl(`conversations/${id}/name`, appSourceType, installedAppId), { body: { name } })
}
export const generationConversationName = async (isInstalledApp: boolean, installedAppId = '', id: string) => {
return getAction('post', isInstalledApp)(getUrl(`conversations/${id}/name`, isInstalledApp, installedAppId), { body: { auto_generate: true } }) as Promise<ConversationItem>
export const generationConversationName = async (appSourceType: AppSourceType, installedAppId = '', id: string) => {
return getAction('post', appSourceType)(getUrl(`conversations/${id}/name`, appSourceType, installedAppId), { body: { auto_generate: true } }) as Promise<ConversationItem>
}
export const fetchChatList = async (conversationId: string, isInstalledApp: boolean, installedAppId = '') => {
return getAction('get', isInstalledApp)(getUrl('messages', isInstalledApp, installedAppId), { params: { conversation_id: conversationId, limit: 20, last_id: '' } }) as any
export const fetchChatList = async (conversationId: string, appSourceType: AppSourceType, installedAppId = '') => {
return getAction('get', appSourceType)(getUrl('messages', appSourceType, installedAppId), { params: { conversation_id: conversationId, limit: 20, last_id: '' } }) as any
}
// Abandoned API interface
@@ -198,12 +191,12 @@ export const fetchChatList = async (conversationId: string, isInstalledApp: bool
// }
// init value. wait for server update
export const fetchAppParams = async (isInstalledApp: boolean, installedAppId = '') => {
return (getAction('get', isInstalledApp))(getUrl('parameters', isInstalledApp, installedAppId)) as Promise<ChatConfig>
export const fetchAppParams = async (appSourceType: AppSourceType, appId = '') => {
return (getAction('get', appSourceType))(getUrl('parameters', appSourceType, appId)) as Promise<ChatConfig>
}
export const fetchWebSAMLSSOUrl = async (appCode: string, redirectUrl: string) => {
return (getAction('get', false))(getUrl('/enterprise/sso/saml/login', false, ''), {
return (getAction('get', AppSourceType.webApp))(getUrl('/enterprise/sso/saml/login', AppSourceType.webApp, ''), {
params: {
app_code: appCode,
redirect_url: redirectUrl,
@@ -212,7 +205,7 @@ export const fetchWebSAMLSSOUrl = async (appCode: string, redirectUrl: string) =
}
export const fetchWebOIDCSSOUrl = async (appCode: string, redirectUrl: string) => {
return (getAction('get', false))(getUrl('/enterprise/sso/oidc/login', false, ''), {
return (getAction('get', AppSourceType.webApp))(getUrl('/enterprise/sso/oidc/login', AppSourceType.webApp, ''), {
params: {
app_code: appCode,
redirect_url: redirectUrl,
@@ -222,7 +215,7 @@ export const fetchWebOIDCSSOUrl = async (appCode: string, redirectUrl: string) =
}
export const fetchWebOAuth2SSOUrl = async (appCode: string, redirectUrl: string) => {
return (getAction('get', false))(getUrl('/enterprise/sso/oauth2/login', false, ''), {
return (getAction('get', AppSourceType.webApp))(getUrl('/enterprise/sso/oauth2/login', AppSourceType.webApp, ''), {
params: {
app_code: appCode,
redirect_url: redirectUrl,
@@ -231,7 +224,7 @@ export const fetchWebOAuth2SSOUrl = async (appCode: string, redirectUrl: string)
}
export const fetchMembersSAMLSSOUrl = async (appCode: string, redirectUrl: string) => {
return (getAction('get', false))(getUrl('/enterprise/sso/members/saml/login', false, ''), {
return (getAction('get', AppSourceType.webApp))(getUrl('/enterprise/sso/members/saml/login', AppSourceType.webApp, ''), {
params: {
app_code: appCode,
redirect_url: redirectUrl,
@@ -240,7 +233,7 @@ export const fetchMembersSAMLSSOUrl = async (appCode: string, redirectUrl: strin
}
export const fetchMembersOIDCSSOUrl = async (appCode: string, redirectUrl: string) => {
return (getAction('get', false))(getUrl('/enterprise/sso/members/oidc/login', false, ''), {
return (getAction('get', AppSourceType.webApp))(getUrl('/enterprise/sso/members/oidc/login', AppSourceType.webApp, ''), {
params: {
app_code: appCode,
redirect_url: redirectUrl,
@@ -250,7 +243,7 @@ export const fetchMembersOIDCSSOUrl = async (appCode: string, redirectUrl: strin
}
export const fetchMembersOAuth2SSOUrl = async (appCode: string, redirectUrl: string) => {
return (getAction('get', false))(getUrl('/enterprise/sso/members/oauth2/login', false, ''), {
return (getAction('get', AppSourceType.webApp))(getUrl('/enterprise/sso/members/oauth2/login', AppSourceType.webApp, ''), {
params: {
app_code: appCode,
redirect_url: redirectUrl,
@@ -258,48 +251,50 @@ export const fetchMembersOAuth2SSOUrl = async (appCode: string, redirectUrl: str
}) as Promise<{ url: string }>
}
export const fetchAppMeta = async (isInstalledApp: boolean, installedAppId = '') => {
return (getAction('get', isInstalledApp))(getUrl('meta', isInstalledApp, installedAppId)) as Promise<AppMeta>
export const fetchAppMeta = async (appSourceType: AppSourceType, installedAppId = '') => {
return (getAction('get', appSourceType))(getUrl('meta', appSourceType, installedAppId)) as Promise<AppMeta>
}
export const updateFeedback = async ({ url, body }: { url: string, body: FeedbackType }, isInstalledApp: boolean, installedAppId = '') => {
return (getAction('post', isInstalledApp))(getUrl(url, isInstalledApp, installedAppId), { body })
export const updateFeedback = async ({ url, body }: { url: string, body: FeedbackType }, appSourceType: AppSourceType, installedAppId = '') => {
return (getAction('post', appSourceType))(getUrl(url, appSourceType, installedAppId), { body })
}
export const fetchMoreLikeThis = async (messageId: string, isInstalledApp: boolean, installedAppId = '') => {
return (getAction('get', isInstalledApp))(getUrl(`/messages/${messageId}/more-like-this`, isInstalledApp, installedAppId), {
export const fetchMoreLikeThis = async (messageId: string, appSourceType: AppSourceType, installedAppId = '') => {
return (getAction('get', appSourceType))(getUrl(`/messages/${messageId}/more-like-this`, appSourceType, installedAppId), {
params: {
response_mode: 'blocking',
},
})
}
export const saveMessage = (messageId: string, isInstalledApp: boolean, installedAppId = '') => {
return (getAction('post', isInstalledApp))(getUrl('/saved-messages', isInstalledApp, installedAppId), { body: { message_id: messageId } })
export const saveMessage = (messageId: string, appSourceType: AppSourceType, installedAppId = '') => {
return (getAction('post', appSourceType))(getUrl('/saved-messages', appSourceType, installedAppId), { body: { message_id: messageId } })
}
export const fetchSavedMessage = async (isInstalledApp: boolean, installedAppId = '') => {
return (getAction('get', isInstalledApp))(getUrl('/saved-messages', isInstalledApp, installedAppId))
export const fetchSavedMessage = async (appSourceType: AppSourceType, installedAppId = '') => {
return (getAction('get', appSourceType))(getUrl('/saved-messages', appSourceType, installedAppId), {}, {
silent: true,
})
}
export const removeMessage = (messageId: string, isInstalledApp: boolean, installedAppId = '') => {
return (getAction('del', isInstalledApp))(getUrl(`/saved-messages/${messageId}`, isInstalledApp, installedAppId))
export const removeMessage = (messageId: string, appSourceType: AppSourceType, installedAppId = '') => {
return (getAction('del', appSourceType))(getUrl(`/saved-messages/${messageId}`, appSourceType, installedAppId))
}
export const fetchSuggestedQuestions = (messageId: string, isInstalledApp: boolean, installedAppId = '') => {
return (getAction('get', isInstalledApp))(getUrl(`/messages/${messageId}/suggested-questions`, isInstalledApp, installedAppId))
export const fetchSuggestedQuestions = (messageId: string, appSourceType: AppSourceType, installedAppId = '') => {
return (getAction('get', appSourceType))(getUrl(`/messages/${messageId}/suggested-questions`, appSourceType, installedAppId))
}
export const audioToText = (url: string, isPublicAPI: boolean, body: FormData) => {
return (getAction('post', !isPublicAPI))(url, { body }, { bodyStringify: false, deleteContentType: true }) as Promise<{ text: string }>
export const audioToText = (url: string, appSourceType: AppSourceType, body: FormData) => {
return (getAction('post', appSourceType))(url, { body }, { bodyStringify: false, deleteContentType: true }) as Promise<{ text: string }>
}
export const textToAudio = (url: string, isPublicAPI: boolean, body: FormData) => {
return (getAction('post', !isPublicAPI))(url, { body }, { bodyStringify: false, deleteContentType: true }) as Promise<{ data: string }>
export const textToAudioStream = (url: string, appSourceType: AppSourceType, header: { content_type: string }, body: { streaming: boolean, voice?: string, message_id?: string, text?: string | null | undefined }) => {
return (getAction('post', appSourceType))(url, { body, header }, { needAllResponseContent: true })
}
export const textToAudioStream = (url: string, isPublicAPI: boolean, header: { content_type: string }, body: { streaming: boolean, voice?: string, message_id?: string, text?: string | null | undefined }) => {
return (getAction('post', !isPublicAPI))(url, { body, header }, { needAllResponseContent: true })
export const textToAudio = (url: string, appSourceType: AppSourceType, body: FormData) => {
return (getAction('post', appSourceType))(url, { body }, { bodyStringify: false, deleteContentType: true }) as Promise<{ data: string }>
}
export const fetchAccessToken = async ({ userId, appCode }: { userId?: string, appCode: string }) => {
+26
View File
@@ -0,0 +1,26 @@
import type { ChatConfig } from '@/app/components/base/chat/types'
import type { DataSetListResponse } from '@/models/datasets'
import type { TryAppFlowPreview, TryAppInfo } from '@/models/try-app'
import { consoleClient } from '@/service/client'
export const fetchTryAppInfo = (appId: string): Promise<TryAppInfo> => {
return consoleClient.trialApps.info({ params: { appId } })
}
export const fetchTryAppDatasets = (appId: string, ids: string[]): Promise<DataSetListResponse> => {
return consoleClient.trialApps.datasets({
params: { appId },
query: { ids },
})
}
export const fetchTryAppFlowPreview = (appId: string): Promise<TryAppFlowPreview> => {
return consoleClient.trialApps.workflows({ params: { appId } })
.then(res => res as TryAppFlowPreview)
}
export const fetchTryAppParams = (appId: string): Promise<ChatConfig> => {
return consoleClient.trialApps.parameters({ params: { appId } })
}
export type { TryAppInfo } from '@/models/try-app'
+13 -4
View File
@@ -2,8 +2,8 @@ import type { App, AppCategory } from '@/models/explore'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useGlobalPublicStore } from '@/context/global-public-context'
import { AccessMode } from '@/models/access-control'
import { fetchAppList, fetchInstalledAppList, getAppAccessModeByAppId, uninstallApp, updatePinStatus } from './explore'
import { fetchAppMeta, fetchAppParams } from './share'
import { fetchAppList, fetchBanners, fetchInstalledAppList, getAppAccessModeByAppId, uninstallApp, updatePinStatus } from './explore'
import { AppSourceType, fetchAppMeta, fetchAppParams } from './share'
const NAME_SPACE = 'explore'
@@ -81,7 +81,7 @@ export const useGetInstalledAppParams = (appId: string | null) => {
queryFn: () => {
if (!appId || appId.length === 0)
return Promise.reject(new Error('App ID is required to get app params'))
return fetchAppParams(true, appId)
return fetchAppParams(AppSourceType.installedApp, appId)
},
enabled: !!appId,
})
@@ -93,8 +93,17 @@ export const useGetInstalledAppMeta = (appId: string | null) => {
queryFn: () => {
if (!appId || appId.length === 0)
return Promise.reject(new Error('App ID is required to get app meta'))
return fetchAppMeta(true, appId)
return fetchAppMeta(AppSourceType.installedApp, appId)
},
enabled: !!appId,
})
}
export const useGetBanners = (locale?: string) => {
return useQuery({
queryKey: [NAME_SPACE, 'banners', locale],
queryFn: () => {
return fetchBanners(locale)
},
})
}
+24 -12
View File
@@ -3,6 +3,7 @@ import type { AppConversationData, ConversationItem } from '@/models/share'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { act, renderHook, waitFor } from '@testing-library/react'
import {
AppSourceType,
fetchChatList,
fetchConversations,
generationConversationName,
@@ -15,15 +16,19 @@ import {
useShareConversations,
} from './use-share'
vi.mock('./share', () => ({
fetchChatList: vi.fn(),
fetchConversations: vi.fn(),
generationConversationName: vi.fn(),
fetchAppInfo: vi.fn(),
fetchAppMeta: vi.fn(),
fetchAppParams: vi.fn(),
getAppAccessModeByAppCode: vi.fn(),
}))
vi.mock('./share', async (importOriginal) => {
const actual = await importOriginal<typeof import('./share')>()
return {
...actual,
fetchChatList: vi.fn(),
fetchConversations: vi.fn(),
generationConversationName: vi.fn(),
fetchAppInfo: vi.fn(),
fetchAppMeta: vi.fn(),
fetchAppParams: vi.fn(),
getAppAccessModeByAppCode: vi.fn(),
}
})
const mockFetchConversations = vi.mocked(fetchConversations)
const mockFetchChatList = vi.mocked(fetchChatList)
@@ -80,6 +85,7 @@ describe('useShareConversations', () => {
appId: undefined,
pinned: true,
limit: 50,
appSourceType: AppSourceType.webApp,
}
const response = createConversationData()
mockFetchConversations.mockResolvedValueOnce(response)
@@ -89,7 +95,7 @@ describe('useShareConversations', () => {
// Assert
await waitFor(() => {
expect(mockFetchConversations).toHaveBeenCalledWith(false, undefined, undefined, true, 50)
expect(mockFetchConversations).toHaveBeenCalledWith(AppSourceType.webApp, undefined, undefined, true, 50)
})
await waitFor(() => {
expect(result.current.data).toEqual(response)
@@ -102,6 +108,7 @@ describe('useShareConversations', () => {
const params = {
isInstalledApp: true,
appId: undefined,
appSourceType: AppSourceType.installedApp,
}
// Act
@@ -127,6 +134,7 @@ describe('useShareChatList', () => {
conversationId: 'conversation-1',
isInstalledApp: true,
appId: 'app-1',
appSourceType: AppSourceType.installedApp,
}
const response = { data: [] }
mockFetchChatList.mockResolvedValueOnce(response)
@@ -136,7 +144,7 @@ describe('useShareChatList', () => {
// Assert
await waitFor(() => {
expect(mockFetchChatList).toHaveBeenCalledWith('conversation-1', true, 'app-1')
expect(mockFetchChatList).toHaveBeenCalledWith('conversation-1', AppSourceType.installedApp, 'app-1')
})
await waitFor(() => {
expect(result.current.data).toEqual(response)
@@ -149,6 +157,7 @@ describe('useShareChatList', () => {
conversationId: '',
isInstalledApp: false,
appId: undefined,
appSourceType: AppSourceType.webApp,
}
// Act
@@ -171,6 +180,7 @@ describe('useShareChatList', () => {
conversationId: 'conversation-1',
isInstalledApp: false,
appId: undefined,
appSourceType: AppSourceType.webApp,
}
const initialResponse = { data: [{ id: '1', content: 'initial' }] }
const updatedResponse = { data: [{ id: '1', content: 'initial' }, { id: '2', content: 'new message' }] }
@@ -219,6 +229,7 @@ describe('useShareConversationName', () => {
conversationId: 'conversation-2',
isInstalledApp: false,
appId: undefined,
appSourceType: AppSourceType.webApp,
}
const response = createConversationItem({ id: 'conversation-2', name: 'Generated' })
mockGenerationConversationName.mockResolvedValueOnce(response)
@@ -228,7 +239,7 @@ describe('useShareConversationName', () => {
// Assert
await waitFor(() => {
expect(mockGenerationConversationName).toHaveBeenCalledWith(false, undefined, 'conversation-2')
expect(mockGenerationConversationName).toHaveBeenCalledWith(AppSourceType.webApp, undefined, 'conversation-2')
})
await waitFor(() => {
expect(result.current.data).toEqual(response)
@@ -241,6 +252,7 @@ describe('useShareConversationName', () => {
conversationId: 'conversation-3',
isInstalledApp: false,
appId: undefined,
appSourceType: AppSourceType.webApp,
}
// Act
+12 -11
View File
@@ -1,6 +1,7 @@
import type { AppConversationData, ConversationItem } from '@/models/share'
import { useQuery } from '@tanstack/react-query'
import {
AppSourceType,
fetchAppInfo,
fetchAppMeta,
fetchAppParams,
@@ -14,7 +15,7 @@ import { useInvalid } from './use-base'
const NAME_SPACE = 'webapp'
type ShareConversationsParams = {
isInstalledApp: boolean
appSourceType: AppSourceType
appId?: string
lastId?: string
pinned?: boolean
@@ -23,13 +24,13 @@ type ShareConversationsParams = {
type ShareChatListParams = {
conversationId: string
isInstalledApp: boolean
appSourceType: AppSourceType
appId?: string
}
type ShareConversationNameParams = {
conversationId: string
isInstalledApp: boolean
appSourceType: AppSourceType
appId?: string
}
@@ -73,7 +74,7 @@ export const useGetWebAppParams = () => {
return useQuery({
queryKey: shareQueryKeys.appParams,
queryFn: () => {
return fetchAppParams(false)
return fetchAppParams(AppSourceType.webApp)
},
})
}
@@ -82,7 +83,7 @@ export const useGetWebAppMeta = () => {
return useQuery({
queryKey: shareQueryKeys.appMeta,
queryFn: () => {
return fetchAppMeta(false)
return fetchAppMeta(AppSourceType.webApp)
},
})
}
@@ -93,11 +94,11 @@ export const useShareConversations = (params: ShareConversationsParams, options:
refetchOnReconnect,
refetchOnWindowFocus,
} = options
const isEnabled = enabled && (!params.isInstalledApp || !!params.appId)
const isEnabled = enabled && params.appSourceType !== AppSourceType.tryApp && (params.appSourceType !== AppSourceType.installedApp || !!params.appId)
return useQuery<AppConversationData>({
queryKey: shareQueryKeys.conversationList(params),
queryFn: () => fetchConversations(
params.isInstalledApp,
params.appSourceType,
params.appId,
params.lastId,
params.pinned,
@@ -115,10 +116,10 @@ export const useShareChatList = (params: ShareChatListParams, options: ShareQuer
refetchOnReconnect,
refetchOnWindowFocus,
} = options
const isEnabled = enabled && (!params.isInstalledApp || !!params.appId) && !!params.conversationId
const isEnabled = enabled && params.appSourceType !== AppSourceType.tryApp && (params.appSourceType !== AppSourceType.installedApp || !!params.appId) && !!params.conversationId
return useQuery({
queryKey: shareQueryKeys.chatList(params),
queryFn: () => fetchChatList(params.conversationId, params.isInstalledApp, params.appId),
queryFn: () => fetchChatList(params.conversationId, params.appSourceType, params.appId),
enabled: isEnabled,
refetchOnReconnect,
refetchOnWindowFocus,
@@ -135,10 +136,10 @@ export const useShareConversationName = (params: ShareConversationNameParams, op
refetchOnReconnect,
refetchOnWindowFocus,
} = options
const isEnabled = enabled && (!params.isInstalledApp || !!params.appId) && !!params.conversationId
const isEnabled = enabled && (params.appSourceType !== AppSourceType.installedApp || !!params.appId) && !!params.conversationId
return useQuery<ConversationItem>({
queryKey: shareQueryKeys.conversationName(params),
queryFn: () => generationConversationName(params.isInstalledApp, params.appId, params.conversationId),
queryFn: () => generationConversationName(params.appSourceType, params.appId, params.conversationId),
enabled: isEnabled,
refetchOnReconnect,
refetchOnWindowFocus,
+44
View File
@@ -0,0 +1,44 @@
import type { DataSetListResponse } from '@/models/datasets'
import { useQuery } from '@tanstack/react-query'
import { consoleQuery } from '@/service/client'
import { fetchTryAppDatasets, fetchTryAppFlowPreview, fetchTryAppInfo, fetchTryAppParams } from './try-app'
export const useGetTryAppInfo = (appId: string) => {
return useQuery({
queryKey: consoleQuery.trialApps.info.queryKey({ input: { params: { appId } } }),
queryFn: () => {
return fetchTryAppInfo(appId)
},
enabled: !!appId,
})
}
export const useGetTryAppParams = (appId: string) => {
return useQuery({
queryKey: consoleQuery.trialApps.parameters.queryKey({ input: { params: { appId } } }),
queryFn: () => {
return fetchTryAppParams(appId)
},
enabled: !!appId,
})
}
export const useGetTryAppDataSets = (appId: string, ids: string[]) => {
return useQuery<DataSetListResponse>({
queryKey: consoleQuery.trialApps.datasets.queryKey({ input: { params: { appId }, query: { ids } } }),
queryFn: () => {
return fetchTryAppDatasets(appId, ids)
},
enabled: ids.length > 0,
})
}
export const useGetTryAppFlowPreview = (appId: string, disabled?: boolean) => {
return useQuery({
queryKey: consoleQuery.trialApps.workflows.queryKey({ input: { params: { appId } } }),
enabled: !disabled,
queryFn: () => {
return fetchTryAppFlowPreview(appId)
},
})
}