Introduce Plugins (#13836)
Signed-off-by: yihong0618 <zouzou0208@gmail.com> Signed-off-by: -LAN- <laipz8200@outlook.com> Signed-off-by: xhe <xw897002528@gmail.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: takatost <takatost@gmail.com> Co-authored-by: kurokobo <kuro664@gmail.com> Co-authored-by: Novice Lee <novicelee@NoviPro.local> Co-authored-by: zxhlyh <jasonapring2015@outlook.com> Co-authored-by: AkaraChen <akarachen@outlook.com> Co-authored-by: Yi <yxiaoisme@gmail.com> Co-authored-by: Joel <iamjoel007@gmail.com> Co-authored-by: JzoNg <jzongcode@gmail.com> Co-authored-by: twwu <twwu@dify.ai> Co-authored-by: Hiroshi Fujita <fujita-h@users.noreply.github.com> Co-authored-by: AkaraChen <85140972+AkaraChen@users.noreply.github.com> Co-authored-by: NFish <douxc512@gmail.com> Co-authored-by: Wu Tianwei <30284043+WTW0313@users.noreply.github.com> Co-authored-by: 非法操作 <hjlarry@163.com> Co-authored-by: Novice <857526207@qq.com> Co-authored-by: Hiroki Nagai <82458324+nagaihiroki-git@users.noreply.github.com> Co-authored-by: Gen Sato <52241300+halogen22@users.noreply.github.com> Co-authored-by: eux <euxuuu@gmail.com> Co-authored-by: huangzhuo1949 <167434202+huangzhuo1949@users.noreply.github.com> Co-authored-by: huangzhuo <huangzhuo1@xiaomi.com> Co-authored-by: lotsik <lotsik@mail.ru> Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> Co-authored-by: nite-knite <nkCoding@gmail.com> Co-authored-by: Jyong <76649700+JohnJyong@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: gakkiyomi <gakkiyomi@aliyun.com> Co-authored-by: CN-P5 <heibai2006@gmail.com> Co-authored-by: CN-P5 <heibai2006@qq.com> Co-authored-by: Chuehnone <1897025+chuehnone@users.noreply.github.com> Co-authored-by: yihong <zouzou0208@gmail.com> Co-authored-by: Kevin9703 <51311316+Kevin9703@users.noreply.github.com> Co-authored-by: -LAN- <laipz8200@outlook.com> Co-authored-by: Boris Feld <lothiraldan@gmail.com> Co-authored-by: mbo <himabo@gmail.com> Co-authored-by: mabo <mabo@aeyes.ai> Co-authored-by: Warren Chen <warren.chen830@gmail.com> Co-authored-by: JzoNgKVO <27049666+JzoNgKVO@users.noreply.github.com> Co-authored-by: jiandanfeng <chenjh3@wangsu.com> Co-authored-by: zhu-an <70234959+xhdd123321@users.noreply.github.com> Co-authored-by: zhaoqingyu.1075 <zhaoqingyu.1075@bytedance.com> Co-authored-by: 海狸大師 <86974027+yenslife@users.noreply.github.com> Co-authored-by: Xu Song <xusong.vip@gmail.com> Co-authored-by: rayshaw001 <396301947@163.com> Co-authored-by: Ding Jiatong <dingjiatong@gmail.com> Co-authored-by: Bowen Liang <liangbowen@gf.com.cn> Co-authored-by: JasonVV <jasonwangiii@outlook.com> Co-authored-by: le0zh <newlight@qq.com> Co-authored-by: zhuxinliang <zhuxinliang@didiglobal.com> Co-authored-by: k-zaku <zaku99@outlook.jp> Co-authored-by: luckylhb90 <luckylhb90@gmail.com> Co-authored-by: hobo.l <hobo.l@binance.com> Co-authored-by: jiangbo721 <365065261@qq.com> Co-authored-by: 刘江波 <jiangbo721@163.com> Co-authored-by: Shun Miyazawa <34241526+miya@users.noreply.github.com> Co-authored-by: EricPan <30651140+Egfly@users.noreply.github.com> Co-authored-by: crazywoola <427733928@qq.com> Co-authored-by: sino <sino2322@gmail.com> Co-authored-by: Jhvcc <37662342+Jhvcc@users.noreply.github.com> Co-authored-by: lowell <lowell.hu@zkteco.in> Co-authored-by: Boris Polonsky <BorisPolonsky@users.noreply.github.com> Co-authored-by: Ademílson Tonato <ademilsonft@outlook.com> Co-authored-by: Ademílson Tonato <ademilson.tonato@refurbed.com> Co-authored-by: IWAI, Masaharu <iwaim.sub@gmail.com> Co-authored-by: Yueh-Po Peng (Yabi) <94939112+y10ab1@users.noreply.github.com> Co-authored-by: Jason <ggbbddjm@gmail.com> Co-authored-by: Xin Zhang <sjhpzx@gmail.com> Co-authored-by: yjc980121 <3898524+yjc980121@users.noreply.github.com> Co-authored-by: heyszt <36215648+hieheihei@users.noreply.github.com> Co-authored-by: Abdullah AlOsaimi <osaimiacc@gmail.com> Co-authored-by: Abdullah AlOsaimi <189027247+osaimi@users.noreply.github.com> Co-authored-by: Yingchun Lai <laiyingchun@apache.org> Co-authored-by: Hash Brown <hi@xzd.me> Co-authored-by: zuodongxu <192560071+zuodongxu@users.noreply.github.com> Co-authored-by: Masashi Tomooka <tmokmss@users.noreply.github.com> Co-authored-by: aplio <ryo.091219@gmail.com> Co-authored-by: Obada Khalili <54270856+obadakhalili@users.noreply.github.com> Co-authored-by: Nam Vu <zuzoovn@gmail.com> Co-authored-by: Kei YAMAZAKI <1715090+kei-yamazaki@users.noreply.github.com> Co-authored-by: TechnoHouse <13776377+deephbz@users.noreply.github.com> Co-authored-by: Riddhimaan-Senapati <114703025+Riddhimaan-Senapati@users.noreply.github.com> Co-authored-by: MaFee921 <31881301+2284730142@users.noreply.github.com> Co-authored-by: te-chan <t-nakanome@sakura-is.co.jp> Co-authored-by: HQidea <HQidea@users.noreply.github.com> Co-authored-by: Joshbly <36315710+Joshbly@users.noreply.github.com> Co-authored-by: xhe <xw897002528@gmail.com> Co-authored-by: weiwenyan-dev <154779315+weiwenyan-dev@users.noreply.github.com> Co-authored-by: ex_wenyan.wei <ex_wenyan.wei@tcl.com> Co-authored-by: engchina <12236799+engchina@users.noreply.github.com> Co-authored-by: engchina <atjapan2015@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: 呆萌闷油瓶 <253605712@qq.com> Co-authored-by: Kemal <kemalmeler@outlook.com> Co-authored-by: Lazy_Frog <4590648+lazyFrogLOL@users.noreply.github.com> Co-authored-by: Yi Xiao <54782454+YIXIAO0@users.noreply.github.com> Co-authored-by: Steven sun <98230804+Tuyohai@users.noreply.github.com> Co-authored-by: steven <sunzwj@digitalchina.com> Co-authored-by: Kalo Chin <91766386+fdb02983rhy@users.noreply.github.com> Co-authored-by: Katy Tao <34019945+KatyTao@users.noreply.github.com> Co-authored-by: depy <42985524+h4ckdepy@users.noreply.github.com> Co-authored-by: 胡春东 <gycm520@gmail.com> Co-authored-by: Junjie.M <118170653@qq.com> Co-authored-by: MuYu <mr.muzea@gmail.com> Co-authored-by: Naoki Takashima <39912547+takatea@users.noreply.github.com> Co-authored-by: Summer-Gu <37869445+gubinjie@users.noreply.github.com> Co-authored-by: Fei He <droxer.he@gmail.com> Co-authored-by: ybalbert001 <120714773+ybalbert001@users.noreply.github.com> Co-authored-by: Yuanbo Li <ybalbert@amazon.com> Co-authored-by: douxc <7553076+douxc@users.noreply.github.com> Co-authored-by: liuzhenghua <1090179900@qq.com> Co-authored-by: Wu Jiayang <62842862+Wu-Jiayang@users.noreply.github.com> Co-authored-by: Your Name <you@example.com> Co-authored-by: kimjion <45935338+kimjion@users.noreply.github.com> Co-authored-by: AugNSo <song.tiankai@icloud.com> Co-authored-by: llinvokerl <38915183+llinvokerl@users.noreply.github.com> Co-authored-by: liusurong.lsr <liusurong.lsr@alibaba-inc.com> Co-authored-by: Vasu Negi <vasu-negi@users.noreply.github.com> Co-authored-by: Hundredwz <1808096180@qq.com> Co-authored-by: Xiyuan Chen <52963600+GareArc@users.noreply.github.com>
This commit is contained in:
parent
222df44d21
commit
403e2d58b9
3272 changed files with 66339 additions and 281594 deletions
|
|
@ -1,9 +1,10 @@
|
|||
import { refreshAccessTokenOrRelogin } from './refresh-token'
|
||||
import { API_PREFIX, IS_CE_EDITION, PUBLIC_API_PREFIX } from '@/config'
|
||||
import { refreshAccessTokenOrRelogin } from './refresh-token'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import type { AnnotationReply, MessageEnd, MessageReplace, ThoughtItem } from '@/app/components/base/chat/chat/type'
|
||||
import type { VisionFile } from '@/types/app'
|
||||
import type {
|
||||
AgentLogResponse,
|
||||
IterationFinishedResponse,
|
||||
IterationNextResponse,
|
||||
IterationStartedResponse,
|
||||
|
|
@ -17,28 +18,11 @@ import type {
|
|||
WorkflowStartedResponse,
|
||||
} from '@/types/workflow'
|
||||
import { removeAccessToken } from '@/app/components/share/utils'
|
||||
import type { FetchOptionType, ResponseError } from './fetch'
|
||||
import { ContentType, base, baseOptions, getAccessToken } from './fetch'
|
||||
import { asyncRunSafe } from '@/utils'
|
||||
const TIME_OUT = 100000
|
||||
|
||||
const ContentType = {
|
||||
json: 'application/json',
|
||||
stream: 'text/event-stream',
|
||||
audio: 'audio/mpeg',
|
||||
form: 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
download: 'application/octet-stream', // for download
|
||||
upload: 'multipart/form-data', // for upload
|
||||
}
|
||||
|
||||
const baseOptions = {
|
||||
method: 'GET',
|
||||
mode: 'cors',
|
||||
credentials: 'include', // always send cookies、HTTP Basic authentication.
|
||||
headers: new Headers({
|
||||
'Content-Type': ContentType.json,
|
||||
}),
|
||||
redirect: 'follow',
|
||||
}
|
||||
|
||||
export type IOnDataMoreInfo = {
|
||||
conversationId?: string
|
||||
taskId?: string
|
||||
|
|
@ -70,9 +54,11 @@ export type IOnTextChunk = (textChunk: TextChunkResponse) => void
|
|||
export type IOnTTSChunk = (messageId: string, audioStr: string, audioType?: string) => void
|
||||
export type IOnTTSEnd = (messageId: string, audioStr: string, audioType?: string) => void
|
||||
export type IOnTextReplace = (textReplace: TextReplaceResponse) => void
|
||||
export type IOnAgentLog = (agentLog: AgentLogResponse) => void
|
||||
|
||||
export type IOtherOptions = {
|
||||
isPublicAPI?: boolean
|
||||
isMarketplaceAPI?: boolean
|
||||
bodyStringify?: boolean
|
||||
needAllResponseContent?: boolean
|
||||
deleteContentType?: boolean
|
||||
|
|
@ -100,17 +86,7 @@ export type IOtherOptions = {
|
|||
onTTSChunk?: IOnTTSChunk
|
||||
onTTSEnd?: IOnTTSEnd
|
||||
onTextReplace?: IOnTextReplace
|
||||
}
|
||||
|
||||
type ResponseError = {
|
||||
code: string
|
||||
message: string
|
||||
status: number
|
||||
}
|
||||
|
||||
type FetchOptionType = Omit<RequestInit, 'body'> & {
|
||||
params?: Record<string, any>
|
||||
body?: BodyInit | Record<string, any> | null
|
||||
onAgentLog?: IOnAgentLog
|
||||
}
|
||||
|
||||
function unicodeToChar(text: string) {
|
||||
|
|
@ -118,7 +94,7 @@ function unicodeToChar(text: string) {
|
|||
return ''
|
||||
|
||||
return text.replace(/\\u[0-9a-f]{4}/g, (_match, p1) => {
|
||||
return String.fromCharCode(parseInt(p1, 16))
|
||||
return String.fromCharCode(Number.parseInt(p1, 16))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -126,24 +102,6 @@ function requiredWebSSOLogin() {
|
|||
globalThis.location.href = `/webapp-signin?redirect_url=${globalThis.location.pathname}`
|
||||
}
|
||||
|
||||
function getAccessToken(isPublicAPI?: boolean) {
|
||||
if (isPublicAPI) {
|
||||
const sharedToken = globalThis.location.pathname.split('/').slice(-1)[0]
|
||||
const accessToken = localStorage.getItem('token') || JSON.stringify({ [sharedToken]: '' })
|
||||
let accessTokenJson = { [sharedToken]: '' }
|
||||
try {
|
||||
accessTokenJson = JSON.parse(accessToken)
|
||||
}
|
||||
catch (e) {
|
||||
|
||||
}
|
||||
return accessTokenJson[sharedToken]
|
||||
}
|
||||
else {
|
||||
return localStorage.getItem('console_token') || ''
|
||||
}
|
||||
}
|
||||
|
||||
export function format(text: string) {
|
||||
let res = text.trim()
|
||||
if (res.startsWith('\n'))
|
||||
|
|
@ -174,6 +132,7 @@ const handleStream = (
|
|||
onTTSChunk?: IOnTTSChunk,
|
||||
onTTSEnd?: IOnTTSEnd,
|
||||
onTextReplace?: IOnTextReplace,
|
||||
onAgentLog?: IOnAgentLog,
|
||||
) => {
|
||||
if (!response.ok)
|
||||
throw new Error('Network response was not ok')
|
||||
|
|
@ -274,6 +233,9 @@ const handleStream = (
|
|||
else if (bufferObj.event === 'text_replace') {
|
||||
onTextReplace?.(bufferObj as TextReplaceResponse)
|
||||
}
|
||||
else if (bufferObj.event === 'agent_log') {
|
||||
onAgentLog?.(bufferObj as AgentLogResponse)
|
||||
}
|
||||
else if (bufferObj.event === 'tts_message') {
|
||||
onTTSChunk?.(bufferObj.message_id, bufferObj.audio, bufferObj.audio_type)
|
||||
}
|
||||
|
|
@ -301,115 +263,7 @@ const handleStream = (
|
|||
read()
|
||||
}
|
||||
|
||||
const baseFetch = <T>(
|
||||
url: string,
|
||||
fetchOptions: FetchOptionType,
|
||||
{
|
||||
isPublicAPI = false,
|
||||
bodyStringify = true,
|
||||
needAllResponseContent,
|
||||
deleteContentType,
|
||||
getAbortController,
|
||||
silent,
|
||||
}: IOtherOptions,
|
||||
): Promise<T> => {
|
||||
const options: typeof baseOptions & FetchOptionType = Object.assign({}, baseOptions, fetchOptions)
|
||||
if (getAbortController) {
|
||||
const abortController = new AbortController()
|
||||
getAbortController(abortController)
|
||||
options.signal = abortController.signal
|
||||
}
|
||||
const accessToken = getAccessToken(isPublicAPI)
|
||||
options.headers.set('Authorization', `Bearer ${accessToken}`)
|
||||
|
||||
if (deleteContentType) {
|
||||
options.headers.delete('Content-Type')
|
||||
}
|
||||
else {
|
||||
const contentType = options.headers.get('Content-Type')
|
||||
if (!contentType)
|
||||
options.headers.set('Content-Type', ContentType.json)
|
||||
}
|
||||
|
||||
const urlPrefix = isPublicAPI ? PUBLIC_API_PREFIX : API_PREFIX
|
||||
let urlWithPrefix = (url.startsWith('http://') || url.startsWith('https://'))
|
||||
? url
|
||||
: `${urlPrefix}${url.startsWith('/') ? url : `/${url}`}`
|
||||
|
||||
const { method, params, body } = options
|
||||
// handle query
|
||||
if (method === 'GET' && params) {
|
||||
const paramsArray: string[] = []
|
||||
Object.keys(params).forEach(key =>
|
||||
paramsArray.push(`${key}=${encodeURIComponent(params[key])}`),
|
||||
)
|
||||
if (urlWithPrefix.search(/\?/) === -1)
|
||||
urlWithPrefix += `?${paramsArray.join('&')}`
|
||||
|
||||
else
|
||||
urlWithPrefix += `&${paramsArray.join('&')}`
|
||||
|
||||
delete options.params
|
||||
}
|
||||
|
||||
if (body && bodyStringify)
|
||||
options.body = JSON.stringify(body)
|
||||
|
||||
// Handle timeout
|
||||
return Promise.race([
|
||||
new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
reject(new Error('request timeout'))
|
||||
}, TIME_OUT)
|
||||
}),
|
||||
new Promise((resolve, reject) => {
|
||||
globalThis.fetch(urlWithPrefix, options as RequestInit)
|
||||
.then((res) => {
|
||||
const resClone = res.clone()
|
||||
// Error handler
|
||||
if (!/^(2|3)\d{2}$/.test(String(res.status))) {
|
||||
const bodyJson = res.json()
|
||||
switch (res.status) {
|
||||
case 401:
|
||||
return Promise.reject(resClone)
|
||||
case 403:
|
||||
bodyJson.then((data: ResponseError) => {
|
||||
if (!silent)
|
||||
Toast.notify({ type: 'error', message: data.message })
|
||||
if (data.code === 'already_setup')
|
||||
globalThis.location.href = `${globalThis.location.origin}/signin`
|
||||
})
|
||||
break
|
||||
// fall through
|
||||
default:
|
||||
bodyJson.then((data: ResponseError) => {
|
||||
if (!silent)
|
||||
Toast.notify({ type: 'error', message: data.message })
|
||||
})
|
||||
}
|
||||
return Promise.reject(resClone)
|
||||
}
|
||||
|
||||
// handle delete api. Delete api not return content.
|
||||
if (res.status === 204) {
|
||||
resolve({ result: 'success' })
|
||||
return
|
||||
}
|
||||
|
||||
// return data
|
||||
if (options.headers.get('Content-type') === ContentType.download || options.headers.get('Content-type') === ContentType.audio)
|
||||
resolve(needAllResponseContent ? resClone : res.blob())
|
||||
|
||||
else resolve(needAllResponseContent ? resClone : res.json())
|
||||
})
|
||||
.catch((err) => {
|
||||
if (!silent)
|
||||
Toast.notify({ type: 'error', message: err })
|
||||
reject(err)
|
||||
})
|
||||
}),
|
||||
]) as Promise<T>
|
||||
}
|
||||
const baseFetch = base
|
||||
|
||||
export const upload = (options: any, isPublicAPI?: boolean, url?: string, searchParams?: string): Promise<any> => {
|
||||
const urlPrefix = isPublicAPI ? PUBLIC_API_PREFIX : API_PREFIX
|
||||
|
|
@ -475,19 +329,25 @@ export const ssePost = (
|
|||
onTTSChunk,
|
||||
onTTSEnd,
|
||||
onTextReplace,
|
||||
onAgentLog,
|
||||
onError,
|
||||
getAbortController,
|
||||
} = otherOptions
|
||||
const abortController = new AbortController()
|
||||
|
||||
const token = localStorage.getItem('console_token')
|
||||
|
||||
const options = Object.assign({}, baseOptions, {
|
||||
method: 'POST',
|
||||
signal: abortController.signal,
|
||||
}, fetchOptions)
|
||||
headers: new Headers({
|
||||
Authorization: `Bearer ${token}`,
|
||||
}),
|
||||
} as RequestInit, fetchOptions)
|
||||
|
||||
const contentType = options.headers.get('Content-Type')
|
||||
const contentType = (options.headers as Headers).get('Content-Type')
|
||||
if (!contentType)
|
||||
options.headers.set('Content-Type', ContentType.json)
|
||||
(options.headers as Headers).set('Content-Type', ContentType.json)
|
||||
|
||||
getAbortController?.(abortController)
|
||||
|
||||
|
|
@ -501,7 +361,7 @@ export const ssePost = (
|
|||
options.body = JSON.stringify(body)
|
||||
|
||||
const accessToken = getAccessToken(isPublicAPI)
|
||||
options.headers.set('Authorization', `Bearer ${accessToken}`)
|
||||
options.headers!.set('Authorization', `Bearer ${accessToken}`)
|
||||
|
||||
globalThis.fetch(urlWithPrefix, options as RequestInit)
|
||||
.then((res) => {
|
||||
|
|
@ -540,7 +400,7 @@ export const ssePost = (
|
|||
return
|
||||
}
|
||||
onData?.(str, isFirstMessage, moreInfo)
|
||||
}, onCompleted, onThought, onMessageEnd, onMessageReplace, onFile, onWorkflowStarted, onWorkflowFinished, onNodeStarted, onNodeFinished, onIterationStart, onIterationNext, onIterationFinish, onNodeRetry, onParallelBranchStarted, onParallelBranchFinished, onTextChunk, onTTSChunk, onTTSEnd, onTextReplace)
|
||||
}, onCompleted, onThought, onMessageEnd, onMessageReplace, onFile, onWorkflowStarted, onWorkflowFinished, onNodeStarted, onNodeFinished, onIterationStart, onIterationNext, onIterationFinish, onNodeRetry, onParallelBranchStarted, onParallelBranchFinished, onTextChunk, onTTSChunk, onTTSEnd, onTextReplace, onAgentLog)
|
||||
}).catch((e) => {
|
||||
if (e.toString() !== 'AbortError: The user aborted a request.' && !e.toString().errorMessage.includes('TypeError: Cannot assign to read only property'))
|
||||
Toast.notify({ type: 'error', message: e })
|
||||
|
|
@ -633,10 +493,20 @@ export const getPublic = <T>(url: string, options = {}, otherOptions?: IOtherOpt
|
|||
return get<T>(url, options, { ...otherOptions, isPublicAPI: true })
|
||||
}
|
||||
|
||||
// For Marketplace API
|
||||
export const getMarketplace = <T>(url: string, options = {}, otherOptions?: IOtherOptions) => {
|
||||
return get<T>(url, options, { ...otherOptions, isMarketplaceAPI: true })
|
||||
}
|
||||
|
||||
export const post = <T>(url: string, options = {}, otherOptions?: IOtherOptions) => {
|
||||
return request<T>(url, Object.assign({}, options, { method: 'POST' }), otherOptions)
|
||||
}
|
||||
|
||||
// For Marketplace API
|
||||
export const postMarketplace = <T>(url: string, options = {}, otherOptions?: IOtherOptions) => {
|
||||
return post<T>(url, options, { ...otherOptions, isMarketplaceAPI: true })
|
||||
}
|
||||
|
||||
export const postPublic = <T>(url: string, options = {}, otherOptions?: IOtherOptions) => {
|
||||
return post<T>(url, options, { ...otherOptions, isPublicAPI: true })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -257,10 +257,6 @@ export const fetchFileUploadConfig: Fetcher<FileUploadConfigResponse, { url: str
|
|||
return get<FileUploadConfigResponse>(url)
|
||||
}
|
||||
|
||||
export const fetchFreeQuotaVerify: Fetcher<{ result: string; flag: boolean; reason: string }, string> = (url) => {
|
||||
return get(url) as Promise<{ result: string; flag: boolean; reason: string }>
|
||||
}
|
||||
|
||||
export const fetchNotionConnection: Fetcher<{ data: string }, string> = (url) => {
|
||||
return get(url) as Promise<{ data: string }>
|
||||
}
|
||||
|
|
@ -298,7 +294,7 @@ export const moderate = (url: string, body: { app_id: string; text: string }) =>
|
|||
}
|
||||
|
||||
type RetrievalMethodsRes = {
|
||||
'retrieval_method': RETRIEVE_METHOD[]
|
||||
retrieval_method: RETRIEVE_METHOD[]
|
||||
}
|
||||
export const fetchSupportRetrievalMethods: Fetcher<RetrievalMethodsRes, string> = (url) => {
|
||||
return get<RetrievalMethodsRes>(url)
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@ import type { IOnCompleted, IOnData, IOnError, IOnFile, IOnMessageEnd, IOnMessag
|
|||
import type { ChatPromptConfig, CompletionPromptConfig } from '@/models/debug'
|
||||
import type { ModelModeType } from '@/types/app'
|
||||
import type { ModelParameterRule } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
export type AutomaticRes = {
|
||||
export interface AutomaticRes {
|
||||
prompt: string
|
||||
variables: string[]
|
||||
opening_statement: string
|
||||
error?: string
|
||||
}
|
||||
export type CodeGenRes = {
|
||||
export interface CodeGenRes {
|
||||
code: string
|
||||
language: string[]
|
||||
error?: string
|
||||
|
|
|
|||
205
web/service/fetch.ts
Normal file
205
web/service/fetch.ts
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
import type { AfterResponseHook, BeforeErrorHook, BeforeRequestHook, Hooks } from 'ky'
|
||||
import ky from 'ky'
|
||||
import type { IOtherOptions } from './base'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { API_PREFIX, MARKETPLACE_API_PREFIX, PUBLIC_API_PREFIX } from '@/config'
|
||||
|
||||
const TIME_OUT = 100000
|
||||
|
||||
export const ContentType = {
|
||||
json: 'application/json',
|
||||
stream: 'text/event-stream',
|
||||
audio: 'audio/mpeg',
|
||||
form: 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
download: 'application/octet-stream', // for download
|
||||
downloadZip: 'application/zip', // for download
|
||||
upload: 'multipart/form-data', // for upload
|
||||
}
|
||||
|
||||
export type FetchOptionType = Omit<RequestInit, 'body'> & {
|
||||
params?: Record<string, any>
|
||||
body?: BodyInit | Record<string, any> | null
|
||||
}
|
||||
|
||||
const afterResponse204: AfterResponseHook = async (_request, _options, response) => {
|
||||
if (response.status === 204) return Response.json({ result: 'success' })
|
||||
}
|
||||
|
||||
export type ResponseError = {
|
||||
code: string
|
||||
message: string
|
||||
status: number
|
||||
}
|
||||
|
||||
const afterResponseErrorCode = (otherOptions: IOtherOptions): AfterResponseHook => {
|
||||
return async (_request, _options, response) => {
|
||||
const clonedResponse = response.clone()
|
||||
if (!/^(2|3)\d{2}$/.test(String(clonedResponse.status))) {
|
||||
const bodyJson = clonedResponse.json() as Promise<ResponseError>
|
||||
switch (clonedResponse.status) {
|
||||
case 403:
|
||||
bodyJson.then((data: ResponseError) => {
|
||||
if (!otherOptions.silent)
|
||||
Toast.notify({ type: 'error', message: data.message })
|
||||
if (data.code === 'already_setup')
|
||||
globalThis.location.href = `${globalThis.location.origin}/signin`
|
||||
})
|
||||
break
|
||||
case 401:
|
||||
return Promise.reject(response)
|
||||
// fall through
|
||||
default:
|
||||
bodyJson.then((data: ResponseError) => {
|
||||
if (!otherOptions.silent)
|
||||
Toast.notify({ type: 'error', message: data.message })
|
||||
})
|
||||
return Promise.reject(response)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const beforeErrorToast = (otherOptions: IOtherOptions): BeforeErrorHook => {
|
||||
return (error) => {
|
||||
if (!otherOptions.silent)
|
||||
Toast.notify({ type: 'error', message: error.message })
|
||||
return error
|
||||
}
|
||||
}
|
||||
|
||||
export const getPublicToken = () => {
|
||||
let token = ''
|
||||
const sharedToken = globalThis.location.pathname.split('/').slice(-1)[0]
|
||||
const accessToken = localStorage.getItem('token') || JSON.stringify({ [sharedToken]: '' })
|
||||
let accessTokenJson = { [sharedToken]: '' }
|
||||
try {
|
||||
accessTokenJson = JSON.parse(accessToken)
|
||||
}
|
||||
catch { }
|
||||
token = accessTokenJson[sharedToken]
|
||||
return token || ''
|
||||
}
|
||||
|
||||
export function getAccessToken(isPublicAPI?: boolean) {
|
||||
if (isPublicAPI) {
|
||||
const sharedToken = globalThis.location.pathname.split('/').slice(-1)[0]
|
||||
const accessToken = localStorage.getItem('token') || JSON.stringify({ [sharedToken]: '' })
|
||||
let accessTokenJson = { [sharedToken]: '' }
|
||||
try {
|
||||
accessTokenJson = JSON.parse(accessToken)
|
||||
}
|
||||
catch (e) {
|
||||
|
||||
}
|
||||
return accessTokenJson[sharedToken]
|
||||
}
|
||||
else {
|
||||
return localStorage.getItem('console_token') || ''
|
||||
}
|
||||
}
|
||||
|
||||
const beforeRequestPublicAuthorization: BeforeRequestHook = (request) => {
|
||||
const token = getAccessToken(true)
|
||||
request.headers.set('Authorization', `Bearer ${token}`)
|
||||
}
|
||||
|
||||
const beforeRequestAuthorization: BeforeRequestHook = (request) => {
|
||||
const accessToken = getAccessToken()
|
||||
request.headers.set('Authorization', `Bearer ${accessToken}`)
|
||||
}
|
||||
|
||||
const baseHooks: Hooks = {
|
||||
afterResponse: [
|
||||
afterResponse204,
|
||||
],
|
||||
}
|
||||
|
||||
const baseClient = ky.create({
|
||||
hooks: baseHooks,
|
||||
timeout: TIME_OUT,
|
||||
})
|
||||
|
||||
export const baseOptions: RequestInit = {
|
||||
method: 'GET',
|
||||
mode: 'cors',
|
||||
credentials: 'include', // always send cookies、HTTP Basic authentication.
|
||||
headers: new Headers({
|
||||
'Content-Type': ContentType.json,
|
||||
}),
|
||||
redirect: 'follow',
|
||||
}
|
||||
|
||||
async function base<T>(url: string, options: FetchOptionType = {}, otherOptions: IOtherOptions = {}): Promise<T> {
|
||||
const { params, body, headers, ...init } = Object.assign({}, baseOptions, options)
|
||||
const {
|
||||
isPublicAPI = false,
|
||||
isMarketplaceAPI = false,
|
||||
bodyStringify = true,
|
||||
needAllResponseContent,
|
||||
deleteContentType,
|
||||
getAbortController,
|
||||
} = otherOptions
|
||||
|
||||
const base
|
||||
= isMarketplaceAPI
|
||||
? MARKETPLACE_API_PREFIX
|
||||
: isPublicAPI
|
||||
? PUBLIC_API_PREFIX
|
||||
: API_PREFIX
|
||||
|
||||
if (getAbortController) {
|
||||
const abortController = new AbortController()
|
||||
getAbortController(abortController)
|
||||
options.signal = abortController.signal
|
||||
}
|
||||
|
||||
const fetchPathname = `${base}${url.startsWith('/') ? url : `/${url}`}`
|
||||
|
||||
if (deleteContentType)
|
||||
(headers as any).delete('Content-Type')
|
||||
|
||||
const client = baseClient.extend({
|
||||
hooks: {
|
||||
...baseHooks,
|
||||
beforeError: [
|
||||
...baseHooks.beforeError || [],
|
||||
beforeErrorToast(otherOptions),
|
||||
],
|
||||
beforeRequest: [
|
||||
...baseHooks.beforeRequest || [],
|
||||
isPublicAPI && beforeRequestPublicAuthorization,
|
||||
!isPublicAPI && !isMarketplaceAPI && beforeRequestAuthorization,
|
||||
].filter(Boolean),
|
||||
afterResponse: [
|
||||
...baseHooks.afterResponse || [],
|
||||
afterResponseErrorCode(otherOptions),
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
const res = await client(fetchPathname, {
|
||||
...init,
|
||||
headers,
|
||||
credentials: isMarketplaceAPI
|
||||
? 'omit'
|
||||
: (options.credentials || 'include'),
|
||||
retry: {
|
||||
methods: [],
|
||||
},
|
||||
...(bodyStringify ? { json: body } : { body: body as BodyInit }),
|
||||
searchParams: params,
|
||||
})
|
||||
|
||||
if (needAllResponseContent)
|
||||
return res as T
|
||||
const contentType = res.headers.get('content-type')
|
||||
if (
|
||||
contentType
|
||||
&& [ContentType.download, ContentType.audio, ContentType.downloadZip].includes(contentType)
|
||||
)
|
||||
return await res.blob() as T
|
||||
|
||||
return await res.json() as T
|
||||
}
|
||||
|
||||
export { base }
|
||||
|
|
@ -2,7 +2,7 @@ import groupBy from 'lodash-es/groupBy'
|
|||
import type { MutationOptions } from '@tanstack/react-query'
|
||||
import { useMutation } from '@tanstack/react-query'
|
||||
import { createDocument, createFirstDocument, fetchDefaultProcessRule, fetchFileIndexingEstimate } from '../datasets'
|
||||
import { type IndexingType } from '@/app/components/datasets/create/step-two'
|
||||
import type { IndexingType } from '@/app/components/datasets/create/step-two'
|
||||
import type { ChunkingMode, CrawlOptions, CrawlResultItem, CreateDocumentReq, CustomFile, DataSourceType, FileIndexingEstimateResponse, IndexingEstimateParams, NotionInfo, ProcessRule, ProcessRuleResponse, createDocumentResponse } from '@/models/datasets'
|
||||
import type { DataSourceProvider, NotionPage } from '@/models/common'
|
||||
|
||||
|
|
|
|||
108
web/service/plugins.ts
Normal file
108
web/service/plugins.ts
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
import type { Fetcher } from 'swr'
|
||||
import { get, getMarketplace, post, upload } from './base'
|
||||
import type {
|
||||
Dependency,
|
||||
InstallPackageResponse,
|
||||
Permissions,
|
||||
PluginDeclaration,
|
||||
PluginInfoFromMarketPlace,
|
||||
PluginManifestInMarket,
|
||||
PluginTasksResponse,
|
||||
TaskStatusResponse,
|
||||
UninstallPluginResponse,
|
||||
updatePackageResponse,
|
||||
uploadGitHubResponse,
|
||||
} from '@/app/components/plugins/types'
|
||||
import type {
|
||||
MarketplaceCollectionPluginsResponse,
|
||||
MarketplaceCollectionsResponse,
|
||||
} from '@/app/components/plugins/marketplace/types'
|
||||
|
||||
export const uploadFile = async (file: File, isBundle: boolean) => {
|
||||
const formData = new FormData()
|
||||
formData.append(isBundle ? 'bundle' : 'pkg', file)
|
||||
return upload({
|
||||
xhr: new XMLHttpRequest(),
|
||||
data: formData,
|
||||
}, false, `/workspaces/current/plugin/upload/${isBundle ? 'bundle' : 'pkg'}`)
|
||||
}
|
||||
|
||||
export const updateFromMarketPlace = async (body: Record<string, string>) => {
|
||||
return post<InstallPackageResponse>('/workspaces/current/plugin/upgrade/marketplace', {
|
||||
body,
|
||||
})
|
||||
}
|
||||
|
||||
export const updateFromGitHub = async (repoUrl: string, selectedVersion: string, selectedPackage: string,
|
||||
originalPlugin: string, newPlugin: string) => {
|
||||
return post<updatePackageResponse>('/workspaces/current/plugin/upgrade/github', {
|
||||
body: {
|
||||
repo: repoUrl,
|
||||
version: selectedVersion,
|
||||
package: selectedPackage,
|
||||
original_plugin_unique_identifier: originalPlugin,
|
||||
new_plugin_unique_identifier: newPlugin,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export const uploadGitHub = async (repoUrl: string, selectedVersion: string, selectedPackage: string) => {
|
||||
return post<uploadGitHubResponse>('/workspaces/current/plugin/upload/github', {
|
||||
body: {
|
||||
repo: repoUrl,
|
||||
version: selectedVersion,
|
||||
package: selectedPackage,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export const fetchIcon = (tenantId: string, fileName: string) => {
|
||||
return get(`workspaces/current/plugin/icon?tenant_id=${tenantId}&filename=${fileName}`)
|
||||
}
|
||||
|
||||
export const fetchManifest = async (uniqueIdentifier: string) => {
|
||||
return get<PluginDeclaration>(`/workspaces/current/plugin/fetch-manifest?plugin_unique_identifier=${uniqueIdentifier}`)
|
||||
}
|
||||
|
||||
export const fetchManifestFromMarketPlace = async (uniqueIdentifier: string) => {
|
||||
return getMarketplace<{ data: { plugin: PluginManifestInMarket, version: { version: string } } }>(`/plugins/identifier?unique_identifier=${uniqueIdentifier}`)
|
||||
}
|
||||
|
||||
export const fetchBundleInfoFromMarketPlace = async ({
|
||||
org,
|
||||
name,
|
||||
version,
|
||||
}: Record<string, string>) => {
|
||||
return getMarketplace<{ data: { version: { dependencies: Dependency[] } } }>(`/bundles/${org}/${name}/${version}`)
|
||||
}
|
||||
|
||||
export const fetchPluginInfoFromMarketPlace = async ({
|
||||
org,
|
||||
name,
|
||||
}: Record<string, string>) => {
|
||||
return getMarketplace<{ data: { plugin: PluginInfoFromMarketPlace, version: { version: string } } }>(`/plugins/${org}/${name}`)
|
||||
}
|
||||
|
||||
export const fetchMarketplaceCollections: Fetcher<MarketplaceCollectionsResponse, { url: string; }> = ({ url }) => {
|
||||
return get<MarketplaceCollectionsResponse>(url)
|
||||
}
|
||||
|
||||
export const fetchMarketplaceCollectionPlugins: Fetcher<MarketplaceCollectionPluginsResponse, { url: string }> = ({ url }) => {
|
||||
return get<MarketplaceCollectionPluginsResponse>(url)
|
||||
}
|
||||
|
||||
export const fetchPluginTasks = async () => {
|
||||
return get<PluginTasksResponse>('/workspaces/current/plugin/tasks?page=1&page_size=255')
|
||||
}
|
||||
|
||||
export const checkTaskStatus = async (taskId: string) => {
|
||||
return get<TaskStatusResponse>(`/workspaces/current/plugin/tasks/${taskId}`)
|
||||
}
|
||||
|
||||
export const updatePermission = async (permissions: Permissions) => {
|
||||
return post('/workspaces/current/plugin/permission/change', { body: permissions })
|
||||
}
|
||||
|
||||
export const uninstallPlugin = async (pluginId: string) => {
|
||||
return post<UninstallPluginResponse>('/workspaces/current/plugin/uninstall', { body: { plugin_installation_id: pluginId } })
|
||||
}
|
||||
10
web/service/strategy.ts
Normal file
10
web/service/strategy.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import type { StrategyPluginDetail } from '@/app/components/plugins/types'
|
||||
import { get } from './base'
|
||||
|
||||
export const fetchStrategyList = () => {
|
||||
return get<StrategyPluginDetail[]>('/workspaces/current/agent-providers')
|
||||
}
|
||||
|
||||
export const fetchStrategyDetail = (agentProvider: string) => {
|
||||
return get<StrategyPluginDetail>(`/workspaces/current/agent-provider/${agentProvider}`)
|
||||
}
|
||||
|
|
@ -15,6 +15,10 @@ export const fetchCollectionList = () => {
|
|||
return get<Collection[]>('/workspaces/current/tool-providers')
|
||||
}
|
||||
|
||||
export const fetchCollectionDetail = (collectionName: string) => {
|
||||
return get<Collection>(`/workspaces/current/tool-provider/${collectionName}/info`)
|
||||
}
|
||||
|
||||
export const fetchBuiltInToolList = (collectionName: string) => {
|
||||
return get<Tool[]>(`/workspaces/current/tool-provider/builtin/${collectionName}/tools`)
|
||||
}
|
||||
|
|
|
|||
27
web/service/use-apps.ts
Normal file
27
web/service/use-apps.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { get } from './base'
|
||||
import type { App } from '@/types/app'
|
||||
import type { AppListResponse } from '@/models/app'
|
||||
import { useInvalid } from './use-base'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
|
||||
const NAME_SPACE = 'apps'
|
||||
|
||||
// TODO paging for list
|
||||
const useAppFullListKey = [NAME_SPACE, 'full-list']
|
||||
export const useAppFullList = () => {
|
||||
return useQuery<AppListResponse>({
|
||||
queryKey: useAppFullListKey,
|
||||
queryFn: () => get<AppListResponse>('/apps', { params: { page: 1, limit: 100 } }),
|
||||
})
|
||||
}
|
||||
|
||||
export const useInvalidateAppFullList = () => {
|
||||
return useInvalid(useAppFullListKey)
|
||||
}
|
||||
|
||||
export const useAppDetail = (appID: string) => {
|
||||
return useQuery<App>({
|
||||
queryKey: [NAME_SPACE, 'detail', appID],
|
||||
queryFn: () => get<App>(`/apps/${appID}`),
|
||||
})
|
||||
}
|
||||
14
web/service/use-common.ts
Normal file
14
web/service/use-common.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { get } from './base'
|
||||
import type {
|
||||
FileUploadConfigResponse,
|
||||
} from '@/models/common'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
|
||||
const NAME_SPACE = 'common'
|
||||
|
||||
export const useFileUploadConfig = () => {
|
||||
return useQuery<FileUploadConfigResponse>({
|
||||
queryKey: [NAME_SPACE, 'file-upload-config'],
|
||||
queryFn: () => get<FileUploadConfigResponse>('/files/upload'),
|
||||
})
|
||||
}
|
||||
149
web/service/use-endpoints.ts
Normal file
149
web/service/use-endpoints.ts
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
import { get, post } from './base'
|
||||
import type {
|
||||
EndpointsResponse,
|
||||
} from '@/app/components/plugins/types'
|
||||
import {
|
||||
useMutation,
|
||||
useQuery,
|
||||
useQueryClient,
|
||||
} from '@tanstack/react-query'
|
||||
|
||||
const NAME_SPACE = 'endpoints'
|
||||
|
||||
export const useEndpointList = (pluginID: string) => {
|
||||
return useQuery({
|
||||
queryKey: [NAME_SPACE, 'list', pluginID],
|
||||
queryFn: () => get<EndpointsResponse>('/workspaces/current/endpoints/list/plugin', {
|
||||
params: {
|
||||
plugin_id: pluginID,
|
||||
page: 1,
|
||||
page_size: 100,
|
||||
},
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
export const useInvalidateEndpointList = () => {
|
||||
const queryClient = useQueryClient()
|
||||
return (pluginID: string) => {
|
||||
queryClient.invalidateQueries(
|
||||
{
|
||||
queryKey: [NAME_SPACE, 'list', pluginID],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const useCreateEndpoint = ({
|
||||
onSuccess,
|
||||
onError,
|
||||
}: {
|
||||
onSuccess?: () => void
|
||||
onError?: (error: any) => void
|
||||
}) => {
|
||||
return useMutation({
|
||||
mutationKey: [NAME_SPACE, 'create'],
|
||||
mutationFn: (payload: { pluginUniqueID: string, state: Record<string, any> }) => {
|
||||
const { pluginUniqueID, state } = payload
|
||||
const newName = state.name
|
||||
delete state.name
|
||||
return post('/workspaces/current/endpoints/create', {
|
||||
body: {
|
||||
plugin_unique_identifier: pluginUniqueID,
|
||||
settings: state,
|
||||
name: newName,
|
||||
},
|
||||
})
|
||||
},
|
||||
onSuccess,
|
||||
onError,
|
||||
})
|
||||
}
|
||||
|
||||
export const useUpdateEndpoint = ({
|
||||
onSuccess,
|
||||
onError,
|
||||
}: {
|
||||
onSuccess?: () => void
|
||||
onError?: (error: any) => void
|
||||
}) => {
|
||||
return useMutation({
|
||||
mutationKey: [NAME_SPACE, 'update'],
|
||||
mutationFn: (payload: { endpointID: string, state: Record<string, any> }) => {
|
||||
const { endpointID, state } = payload
|
||||
const newName = state.name
|
||||
delete state.name
|
||||
return post('/workspaces/current/endpoints/update', {
|
||||
body: {
|
||||
endpoint_id: endpointID,
|
||||
settings: state,
|
||||
name: newName,
|
||||
},
|
||||
})
|
||||
},
|
||||
onSuccess,
|
||||
onError,
|
||||
})
|
||||
}
|
||||
|
||||
export const useDeleteEndpoint = ({
|
||||
onSuccess,
|
||||
onError,
|
||||
}: {
|
||||
onSuccess?: () => void
|
||||
onError?: (error: any) => void
|
||||
}) => {
|
||||
return useMutation({
|
||||
mutationKey: [NAME_SPACE, 'delete'],
|
||||
mutationFn: (endpointID: string) => {
|
||||
return post('/workspaces/current/endpoints/delete', {
|
||||
body: {
|
||||
endpoint_id: endpointID,
|
||||
},
|
||||
})
|
||||
},
|
||||
onSuccess,
|
||||
onError,
|
||||
})
|
||||
}
|
||||
|
||||
export const useEnableEndpoint = ({
|
||||
onSuccess,
|
||||
onError,
|
||||
}: {
|
||||
onSuccess?: () => void
|
||||
onError?: (error: any) => void
|
||||
}) => {
|
||||
return useMutation({
|
||||
mutationKey: [NAME_SPACE, 'enable'],
|
||||
mutationFn: (endpointID: string) => {
|
||||
return post('/workspaces/current/endpoints/enable', {
|
||||
body: {
|
||||
endpoint_id: endpointID,
|
||||
},
|
||||
})
|
||||
},
|
||||
onSuccess,
|
||||
onError,
|
||||
})
|
||||
}
|
||||
|
||||
export const useDisableEndpoint = ({
|
||||
onSuccess,
|
||||
onError,
|
||||
}: {
|
||||
onSuccess?: () => void
|
||||
onError?: (error: any) => void
|
||||
}) => {
|
||||
return useMutation({
|
||||
mutationKey: [NAME_SPACE, 'disable'],
|
||||
mutationFn: (endpointID: string) => {
|
||||
return post('/workspaces/current/endpoints/disable', {
|
||||
body: {
|
||||
endpoint_id: endpointID,
|
||||
},
|
||||
})
|
||||
},
|
||||
onSuccess,
|
||||
onError,
|
||||
})
|
||||
}
|
||||
17
web/service/use-models.ts
Normal file
17
web/service/use-models.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { get } from './base'
|
||||
import type {
|
||||
ModelItem,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import {
|
||||
useQuery,
|
||||
// useQueryClient,
|
||||
} from '@tanstack/react-query'
|
||||
|
||||
const NAME_SPACE = 'models'
|
||||
|
||||
export const useModelProviderModelList = (provider: string) => {
|
||||
return useQuery({
|
||||
queryKey: [NAME_SPACE, 'model-list', provider],
|
||||
queryFn: () => get<{ data: ModelItem[] }>(`/workspaces/current/model-providers/${provider}/models`),
|
||||
})
|
||||
}
|
||||
495
web/service/use-plugins.ts
Normal file
495
web/service/use-plugins.ts
Normal file
|
|
@ -0,0 +1,495 @@
|
|||
import { useCallback } from 'react'
|
||||
import type {
|
||||
ModelProvider,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import { fetchModelProviderModelList } from '@/service/common'
|
||||
import { fetchPluginInfoFromMarketPlace } from '@/service/plugins'
|
||||
import type {
|
||||
DebugInfo as DebugInfoTypes,
|
||||
Dependency,
|
||||
GitHubItemAndMarketPlaceDependency,
|
||||
InstallPackageResponse,
|
||||
InstalledPluginListResponse,
|
||||
PackageDependency,
|
||||
Permissions,
|
||||
Plugin,
|
||||
PluginDetail,
|
||||
PluginInfoFromMarketPlace,
|
||||
PluginTask,
|
||||
PluginType,
|
||||
PluginsFromMarketplaceByInfoResponse,
|
||||
PluginsFromMarketplaceResponse,
|
||||
VersionInfo,
|
||||
VersionListResponse,
|
||||
uploadGitHubResponse,
|
||||
} from '@/app/components/plugins/types'
|
||||
import { TaskStatus } from '@/app/components/plugins/types'
|
||||
import { PluginType as PluginTypeEnum } from '@/app/components/plugins/types'
|
||||
import type {
|
||||
PluginsSearchParams,
|
||||
} from '@/app/components/plugins/marketplace/types'
|
||||
import { get, getMarketplace, post, postMarketplace } from './base'
|
||||
import type { MutateOptions, QueryOptions } from '@tanstack/react-query'
|
||||
import {
|
||||
useMutation,
|
||||
useQuery,
|
||||
useQueryClient,
|
||||
} from '@tanstack/react-query'
|
||||
import { useInvalidateAllBuiltInTools } from './use-tools'
|
||||
import usePermission from '@/app/components/plugins/plugin-page/use-permission'
|
||||
import { uninstallPlugin } from '@/service/plugins'
|
||||
import useRefreshPluginList from '@/app/components/plugins/install-plugin/hooks/use-refresh-plugin-list'
|
||||
|
||||
const NAME_SPACE = 'plugins'
|
||||
|
||||
const useInstalledPluginListKey = [NAME_SPACE, 'installedPluginList']
|
||||
export const useCheckInstalled = ({
|
||||
pluginIds,
|
||||
enabled,
|
||||
}: {
|
||||
pluginIds: string[],
|
||||
enabled: boolean
|
||||
}) => {
|
||||
return useQuery<{ plugins: PluginDetail[] }>({
|
||||
queryKey: [NAME_SPACE, 'checkInstalled', pluginIds],
|
||||
queryFn: () => post<{ plugins: PluginDetail[] }>('/workspaces/current/plugin/list/installations/ids', {
|
||||
body: {
|
||||
plugin_ids: pluginIds,
|
||||
},
|
||||
}),
|
||||
enabled,
|
||||
staleTime: 0, // always fresh
|
||||
})
|
||||
}
|
||||
|
||||
export const useInstalledPluginList = (disable?: boolean) => {
|
||||
return useQuery<InstalledPluginListResponse>({
|
||||
queryKey: useInstalledPluginListKey,
|
||||
queryFn: () => get<InstalledPluginListResponse>('/workspaces/current/plugin/list'),
|
||||
enabled: !disable,
|
||||
initialData: !disable ? undefined : { plugins: [] },
|
||||
})
|
||||
}
|
||||
|
||||
export const useInvalidateInstalledPluginList = () => {
|
||||
const queryClient = useQueryClient()
|
||||
const invalidateAllBuiltInTools = useInvalidateAllBuiltInTools()
|
||||
return () => {
|
||||
queryClient.invalidateQueries(
|
||||
{
|
||||
queryKey: useInstalledPluginListKey,
|
||||
})
|
||||
invalidateAllBuiltInTools()
|
||||
}
|
||||
}
|
||||
|
||||
export const useInstallPackageFromMarketPlace = (options?: MutateOptions<InstallPackageResponse, Error, string>) => {
|
||||
return useMutation({
|
||||
...options,
|
||||
mutationFn: (uniqueIdentifier: string) => {
|
||||
return post<InstallPackageResponse>('/workspaces/current/plugin/install/marketplace', { body: { plugin_unique_identifiers: [uniqueIdentifier] } })
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export const useUpdatePackageFromMarketPlace = (options?: MutateOptions<InstallPackageResponse, Error, object>) => {
|
||||
return useMutation({
|
||||
...options,
|
||||
mutationFn: (body: object) => {
|
||||
return post<InstallPackageResponse>('/workspaces/current/plugin/upgrade/marketplace', {
|
||||
body,
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export const useVersionListOfPlugin = (pluginID: string) => {
|
||||
return useQuery<{ data: VersionListResponse }>({
|
||||
enabled: !!pluginID,
|
||||
queryKey: [NAME_SPACE, 'versions', pluginID],
|
||||
queryFn: () => getMarketplace<{ data: VersionListResponse }>(`/plugins/${pluginID}/versions`, { params: { page: 1, page_size: 100 } }),
|
||||
})
|
||||
}
|
||||
export const useInvalidateVersionListOfPlugin = () => {
|
||||
const queryClient = useQueryClient()
|
||||
return (pluginID: string) => {
|
||||
queryClient.invalidateQueries({ queryKey: [NAME_SPACE, 'versions', pluginID] })
|
||||
}
|
||||
}
|
||||
|
||||
export const useInstallPackageFromLocal = () => {
|
||||
return useMutation({
|
||||
mutationFn: (uniqueIdentifier: string) => {
|
||||
return post<InstallPackageResponse>('/workspaces/current/plugin/install/pkg', {
|
||||
body: { plugin_unique_identifiers: [uniqueIdentifier] },
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export const useInstallPackageFromGitHub = () => {
|
||||
return useMutation({
|
||||
mutationFn: ({ repoUrl, selectedVersion, selectedPackage, uniqueIdentifier }: {
|
||||
repoUrl: string
|
||||
selectedVersion: string
|
||||
selectedPackage: string
|
||||
uniqueIdentifier: string
|
||||
}) => {
|
||||
return post<InstallPackageResponse>('/workspaces/current/plugin/install/github', {
|
||||
body: {
|
||||
repo: repoUrl,
|
||||
version: selectedVersion,
|
||||
package: selectedPackage,
|
||||
plugin_unique_identifier: uniqueIdentifier,
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export const useUploadGitHub = (payload: {
|
||||
repo: string
|
||||
version: string
|
||||
package: string
|
||||
}) => {
|
||||
return useQuery({
|
||||
queryKey: [NAME_SPACE, 'uploadGitHub', payload],
|
||||
queryFn: () => post<uploadGitHubResponse>('/workspaces/current/plugin/upload/github', {
|
||||
body: payload,
|
||||
}),
|
||||
retry: 0,
|
||||
})
|
||||
}
|
||||
|
||||
export const useInstallOrUpdate = ({
|
||||
onSuccess,
|
||||
}: {
|
||||
onSuccess?: (res: { success: boolean }[]) => void
|
||||
}) => {
|
||||
const { mutateAsync: updatePackageFromMarketPlace } = useUpdatePackageFromMarketPlace()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (data: {
|
||||
payload: Dependency[],
|
||||
plugin: Plugin[],
|
||||
installedInfo: Record<string, VersionInfo>
|
||||
}) => {
|
||||
const { payload, plugin, installedInfo } = data
|
||||
|
||||
return Promise.all(payload.map(async (item, i) => {
|
||||
try {
|
||||
const orgAndName = `${plugin[i]?.org || plugin[i]?.author}/${plugin[i]?.name}`
|
||||
const installedPayload = installedInfo[orgAndName]
|
||||
const isInstalled = !!installedPayload
|
||||
let uniqueIdentifier = ''
|
||||
|
||||
if (item.type === 'github') {
|
||||
const data = item as GitHubItemAndMarketPlaceDependency
|
||||
// From local bundle don't have data.value.github_plugin_unique_identifier
|
||||
if (!data.value.github_plugin_unique_identifier) {
|
||||
const { unique_identifier } = await post<uploadGitHubResponse>('/workspaces/current/plugin/upload/github', {
|
||||
body: {
|
||||
repo: data.value.repo!,
|
||||
version: data.value.release! || data.value.version!,
|
||||
package: data.value.packages! || data.value.package!,
|
||||
},
|
||||
})
|
||||
uniqueIdentifier = data.value.github_plugin_unique_identifier! || unique_identifier
|
||||
// has the same version, but not installed
|
||||
if (uniqueIdentifier === installedPayload?.uniqueIdentifier) {
|
||||
return {
|
||||
success: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isInstalled) {
|
||||
await post<InstallPackageResponse>('/workspaces/current/plugin/install/github', {
|
||||
body: {
|
||||
repo: data.value.repo!,
|
||||
version: data.value.release! || data.value.version!,
|
||||
package: data.value.packages! || data.value.package!,
|
||||
plugin_unique_identifier: uniqueIdentifier,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
if (item.type === 'marketplace') {
|
||||
const data = item as GitHubItemAndMarketPlaceDependency
|
||||
uniqueIdentifier = data.value.plugin_unique_identifier! || plugin[i]?.plugin_id
|
||||
if (uniqueIdentifier === installedPayload?.uniqueIdentifier) {
|
||||
return {
|
||||
success: true,
|
||||
}
|
||||
}
|
||||
if (!isInstalled) {
|
||||
await post<InstallPackageResponse>('/workspaces/current/plugin/install/marketplace', {
|
||||
body: {
|
||||
plugin_unique_identifiers: [uniqueIdentifier],
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
if (item.type === 'package') {
|
||||
const data = item as PackageDependency
|
||||
uniqueIdentifier = data.value.unique_identifier
|
||||
if (uniqueIdentifier === installedPayload?.uniqueIdentifier) {
|
||||
return {
|
||||
success: true,
|
||||
}
|
||||
}
|
||||
if (!isInstalled) {
|
||||
await post<InstallPackageResponse>('/workspaces/current/plugin/install/pkg', {
|
||||
body: {
|
||||
plugin_unique_identifiers: [uniqueIdentifier],
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
if (isInstalled) {
|
||||
if (item.type === 'package') {
|
||||
await uninstallPlugin(installedPayload.installedId)
|
||||
await post<InstallPackageResponse>('/workspaces/current/plugin/install/pkg', {
|
||||
body: {
|
||||
plugin_unique_identifiers: [uniqueIdentifier],
|
||||
},
|
||||
})
|
||||
}
|
||||
else {
|
||||
await updatePackageFromMarketPlace({
|
||||
original_plugin_unique_identifier: installedPayload?.uniqueIdentifier,
|
||||
new_plugin_unique_identifier: uniqueIdentifier,
|
||||
})
|
||||
}
|
||||
}
|
||||
return ({ success: true })
|
||||
}
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars
|
||||
catch (e) {
|
||||
return Promise.resolve({ success: false })
|
||||
}
|
||||
}))
|
||||
},
|
||||
onSuccess,
|
||||
})
|
||||
}
|
||||
|
||||
export const useDebugKey = () => {
|
||||
return useQuery({
|
||||
queryKey: [NAME_SPACE, 'debugKey'],
|
||||
queryFn: () => get<DebugInfoTypes>('/workspaces/current/plugin/debugging-key'),
|
||||
})
|
||||
}
|
||||
|
||||
const usePermissionsKey = [NAME_SPACE, 'permissions']
|
||||
export const usePermissions = () => {
|
||||
return useQuery({
|
||||
queryKey: usePermissionsKey,
|
||||
queryFn: () => get<Permissions>('/workspaces/current/plugin/permission/fetch'),
|
||||
})
|
||||
}
|
||||
|
||||
export const useInvalidatePermissions = () => {
|
||||
const queryClient = useQueryClient()
|
||||
return () => {
|
||||
queryClient.invalidateQueries(
|
||||
{
|
||||
queryKey: usePermissionsKey,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const useMutationPermissions = ({
|
||||
onSuccess,
|
||||
}: {
|
||||
onSuccess?: () => void
|
||||
}) => {
|
||||
return useMutation({
|
||||
mutationFn: (payload: Permissions) => {
|
||||
return post('/workspaces/current/plugin/permission/change', { body: payload })
|
||||
},
|
||||
onSuccess,
|
||||
})
|
||||
}
|
||||
|
||||
export const useMutationPluginsFromMarketplace = () => {
|
||||
return useMutation({
|
||||
mutationFn: (pluginsSearchParams: PluginsSearchParams) => {
|
||||
const {
|
||||
query,
|
||||
sortBy,
|
||||
sortOrder,
|
||||
category,
|
||||
tags,
|
||||
exclude,
|
||||
type,
|
||||
page = 1,
|
||||
pageSize = 40,
|
||||
} = pluginsSearchParams
|
||||
const pluginOrBundle = type === 'bundle' ? 'bundles' : 'plugins'
|
||||
return postMarketplace<{ data: PluginsFromMarketplaceResponse }>(`/${pluginOrBundle}/search/advanced`, {
|
||||
body: {
|
||||
page,
|
||||
page_size: pageSize,
|
||||
query,
|
||||
sort_by: sortBy,
|
||||
sort_order: sortOrder,
|
||||
category: category !== 'all' ? category : '',
|
||||
tags,
|
||||
exclude,
|
||||
type,
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export const useFetchPluginsInMarketPlaceByIds = (unique_identifiers: string[], options?: QueryOptions<{ data: PluginsFromMarketplaceResponse }>) => {
|
||||
return useQuery({
|
||||
...options,
|
||||
queryKey: [NAME_SPACE, 'fetchPluginsInMarketPlaceByIds', unique_identifiers],
|
||||
queryFn: () => postMarketplace<{ data: PluginsFromMarketplaceResponse }>('/plugins/identifier/batch', {
|
||||
body: {
|
||||
unique_identifiers,
|
||||
},
|
||||
}),
|
||||
enabled: unique_identifiers?.filter(i => !!i).length > 0,
|
||||
retry: 0,
|
||||
})
|
||||
}
|
||||
|
||||
export const useFetchPluginsInMarketPlaceByInfo = (infos: Record<string, any>[]) => {
|
||||
return useQuery({
|
||||
queryKey: [NAME_SPACE, 'fetchPluginsInMarketPlaceByInfo', infos],
|
||||
queryFn: () => postMarketplace<{ data: PluginsFromMarketplaceByInfoResponse }>('/plugins/versions/batch', {
|
||||
body: {
|
||||
plugin_tuples: infos.map(info => ({
|
||||
org: info.organization,
|
||||
name: info.plugin,
|
||||
version: info.version,
|
||||
})),
|
||||
},
|
||||
}),
|
||||
enabled: infos?.filter(i => !!i).length > 0,
|
||||
retry: 0,
|
||||
})
|
||||
}
|
||||
|
||||
const usePluginTaskListKey = [NAME_SPACE, 'pluginTaskList']
|
||||
export const usePluginTaskList = (category?: PluginType) => {
|
||||
const {
|
||||
canManagement,
|
||||
} = usePermission()
|
||||
const { refreshPluginList } = useRefreshPluginList()
|
||||
const {
|
||||
data,
|
||||
isFetched,
|
||||
refetch,
|
||||
...rest
|
||||
} = useQuery({
|
||||
enabled: canManagement,
|
||||
queryKey: usePluginTaskListKey,
|
||||
queryFn: () => get<{ tasks: PluginTask[] }>('/workspaces/current/plugin/tasks?page=1&page_size=100'),
|
||||
refetchInterval: (lastQuery) => {
|
||||
const lastData = lastQuery.state.data
|
||||
const taskDone = lastData?.tasks.every(task => task.status === TaskStatus.success || task.status === TaskStatus.failed)
|
||||
const taskAllFailed = lastData?.tasks.every(task => task.status === TaskStatus.failed)
|
||||
if (taskDone) {
|
||||
if (lastData?.tasks.length && !taskAllFailed)
|
||||
refreshPluginList(category ? { category } as any : undefined, !category)
|
||||
return false
|
||||
}
|
||||
|
||||
return 5000
|
||||
},
|
||||
})
|
||||
const handleRefetch = useCallback(() => {
|
||||
refetch()
|
||||
}, [refetch])
|
||||
|
||||
return {
|
||||
data,
|
||||
pluginTasks: data?.tasks || [],
|
||||
isFetched,
|
||||
handleRefetch,
|
||||
...rest,
|
||||
}
|
||||
}
|
||||
|
||||
export const useMutationClearTaskPlugin = () => {
|
||||
return useMutation({
|
||||
mutationFn: ({ taskId, pluginId }: { taskId: string; pluginId: string }) => {
|
||||
return post<{ success: boolean }>(`/workspaces/current/plugin/tasks/${taskId}/delete/${pluginId}`)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export const useMutationClearAllTaskPlugin = () => {
|
||||
return useMutation({
|
||||
mutationFn: () => {
|
||||
return post<{ success: boolean }>('/workspaces/current/plugin/tasks/delete_all')
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export const usePluginManifestInfo = (pluginUID: string) => {
|
||||
return useQuery({
|
||||
enabled: !!pluginUID,
|
||||
queryKey: [[NAME_SPACE, 'manifest', pluginUID]],
|
||||
queryFn: () => getMarketplace<{ data: { plugin: PluginInfoFromMarketPlace, version: { version: string } } }>(`/plugins/${pluginUID}`),
|
||||
retry: 0,
|
||||
})
|
||||
}
|
||||
|
||||
export const useDownloadPlugin = (info: { organization: string; pluginName: string; version: string }, needDownload: boolean) => {
|
||||
return useQuery({
|
||||
queryKey: [NAME_SPACE, 'downloadPlugin', info],
|
||||
queryFn: () => getMarketplace<Blob>(`/plugins/${info.organization}/${info.pluginName}/${info.version}/download`),
|
||||
enabled: needDownload,
|
||||
retry: 0,
|
||||
})
|
||||
}
|
||||
|
||||
export const useMutationCheckDependencies = () => {
|
||||
return useMutation({
|
||||
mutationFn: (appId: string) => {
|
||||
return get<{ leaked_dependencies: Dependency[] }>(`/apps/imports/${appId}/check-dependencies`)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export const useModelInList = (currentProvider?: ModelProvider, modelId?: string) => {
|
||||
return useQuery({
|
||||
queryKey: ['modelInList', currentProvider?.provider, modelId],
|
||||
queryFn: async () => {
|
||||
if (!modelId || !currentProvider) return false
|
||||
try {
|
||||
const modelsData = await fetchModelProviderModelList(`/workspaces/current/model-providers/${currentProvider?.provider}/models`)
|
||||
return !!modelId && !!modelsData.data.find(item => item.model === modelId)
|
||||
}
|
||||
catch (error) {
|
||||
return false
|
||||
}
|
||||
},
|
||||
enabled: !!modelId && !!currentProvider,
|
||||
})
|
||||
}
|
||||
|
||||
export const usePluginInfo = (providerName?: string) => {
|
||||
return useQuery({
|
||||
queryKey: ['pluginInfo', providerName],
|
||||
queryFn: async () => {
|
||||
if (!providerName) return null
|
||||
const parts = providerName.split('/')
|
||||
const org = parts[0]
|
||||
const name = parts[1]
|
||||
try {
|
||||
const response = await fetchPluginInfoFromMarketPlace({ org, name })
|
||||
return response.data.plugin.category === PluginTypeEnum.model ? response.data.plugin : null
|
||||
}
|
||||
catch (error) {
|
||||
return null
|
||||
}
|
||||
},
|
||||
enabled: !!providerName,
|
||||
})
|
||||
}
|
||||
36
web/service/use-strategy.ts
Normal file
36
web/service/use-strategy.ts
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import type {
|
||||
StrategyPluginDetail,
|
||||
} from '@/app/components/plugins/types'
|
||||
import { useInvalid } from './use-base'
|
||||
import type { QueryOptions } from '@tanstack/react-query'
|
||||
import {
|
||||
useQuery,
|
||||
} from '@tanstack/react-query'
|
||||
import { fetchStrategyDetail, fetchStrategyList } from './strategy'
|
||||
|
||||
const NAME_SPACE = 'agent_strategy'
|
||||
|
||||
const useStrategyListKey = [NAME_SPACE, 'strategyList']
|
||||
export const useStrategyProviders = () => {
|
||||
return useQuery<StrategyPluginDetail[]>({
|
||||
queryKey: useStrategyListKey,
|
||||
queryFn: fetchStrategyList,
|
||||
})
|
||||
}
|
||||
|
||||
export const useInvalidateStrategyProviders = () => {
|
||||
return useInvalid(useStrategyListKey)
|
||||
}
|
||||
|
||||
export const useStrategyProviderDetail = (agentProvider: string, options?: QueryOptions<StrategyPluginDetail>) => {
|
||||
return useQuery<StrategyPluginDetail>({
|
||||
...options,
|
||||
queryKey: [NAME_SPACE, 'detail', agentProvider],
|
||||
queryFn: () => fetchStrategyDetail(agentProvider),
|
||||
enabled: !!agentProvider,
|
||||
})
|
||||
}
|
||||
|
||||
export const useInvalidateStrategyProviderDetail = (agentProvider: string) => {
|
||||
return useInvalid([NAME_SPACE, 'detail', agentProvider])
|
||||
}
|
||||
121
web/service/use-tools.ts
Normal file
121
web/service/use-tools.ts
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
import { get, post } from './base'
|
||||
import type {
|
||||
Collection,
|
||||
Tool,
|
||||
} from '@/app/components/tools/types'
|
||||
import type { ToolWithProvider } from '@/app/components/workflow/types'
|
||||
import { useInvalid } from './use-base'
|
||||
import {
|
||||
useMutation,
|
||||
useQuery,
|
||||
useQueryClient,
|
||||
} from '@tanstack/react-query'
|
||||
|
||||
const NAME_SPACE = 'tools'
|
||||
|
||||
const useAllToolProvidersKey = [NAME_SPACE, 'allToolProviders']
|
||||
export const useAllToolProviders = () => {
|
||||
return useQuery<Collection[]>({
|
||||
queryKey: useAllToolProvidersKey,
|
||||
queryFn: () => get<Collection[]>('/workspaces/current/tool-providers'),
|
||||
})
|
||||
}
|
||||
|
||||
export const useInvalidateAllToolProviders = () => {
|
||||
return useInvalid(useAllToolProvidersKey)
|
||||
}
|
||||
|
||||
const useAllBuiltInToolsKey = [NAME_SPACE, 'builtIn']
|
||||
export const useAllBuiltInTools = () => {
|
||||
return useQuery<ToolWithProvider[]>({
|
||||
queryKey: useAllBuiltInToolsKey,
|
||||
queryFn: () => get<ToolWithProvider[]>('/workspaces/current/tools/builtin'),
|
||||
})
|
||||
}
|
||||
|
||||
export const useInvalidateAllBuiltInTools = () => {
|
||||
return useInvalid(useAllBuiltInToolsKey)
|
||||
}
|
||||
|
||||
const useAllCustomToolsKey = [NAME_SPACE, 'customTools']
|
||||
export const useAllCustomTools = () => {
|
||||
return useQuery<ToolWithProvider[]>({
|
||||
queryKey: useAllCustomToolsKey,
|
||||
queryFn: () => get<ToolWithProvider[]>('/workspaces/current/tools/api'),
|
||||
})
|
||||
}
|
||||
|
||||
export const useInvalidateAllCustomTools = () => {
|
||||
return useInvalid(useAllCustomToolsKey)
|
||||
}
|
||||
|
||||
const useAllWorkflowToolsKey = [NAME_SPACE, 'workflowTools']
|
||||
export const useAllWorkflowTools = () => {
|
||||
return useQuery<ToolWithProvider[]>({
|
||||
queryKey: useAllWorkflowToolsKey,
|
||||
queryFn: () => get<ToolWithProvider[]>('/workspaces/current/tools/workflow'),
|
||||
})
|
||||
}
|
||||
|
||||
export const useInvalidateAllWorkflowTools = () => {
|
||||
return useInvalid(useAllWorkflowToolsKey)
|
||||
}
|
||||
|
||||
export const useBuiltinProviderInfo = (providerName: string) => {
|
||||
return useQuery({
|
||||
queryKey: [NAME_SPACE, 'builtin-provider-info', providerName],
|
||||
queryFn: () => get<Collection>(`/workspaces/current/tool-provider/builtin/${providerName}/info`),
|
||||
})
|
||||
}
|
||||
|
||||
export const useInvalidateBuiltinProviderInfo = () => {
|
||||
const queryClient = useQueryClient()
|
||||
return (providerName: string) => {
|
||||
queryClient.invalidateQueries(
|
||||
{
|
||||
queryKey: [NAME_SPACE, 'builtin-provider-info', providerName],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const useBuiltinTools = (providerName: string) => {
|
||||
return useQuery({
|
||||
queryKey: [NAME_SPACE, 'builtin-provider-tools', providerName],
|
||||
queryFn: () => get<Tool[]>(`/workspaces/current/tool-provider/builtin/${providerName}/tools`),
|
||||
})
|
||||
}
|
||||
|
||||
export const useUpdateProviderCredentials = ({
|
||||
onSuccess,
|
||||
}: {
|
||||
onSuccess?: () => void
|
||||
}) => {
|
||||
return useMutation({
|
||||
mutationKey: [NAME_SPACE, 'update-provider-credentials'],
|
||||
mutationFn: (payload: { providerName: string, credentials: Record<string, any> }) => {
|
||||
const { providerName, credentials } = payload
|
||||
return post(`/workspaces/current/tool-provider/builtin/${providerName}/update`, {
|
||||
body: {
|
||||
credentials,
|
||||
},
|
||||
})
|
||||
},
|
||||
onSuccess,
|
||||
})
|
||||
}
|
||||
|
||||
export const useRemoveProviderCredentials = ({
|
||||
onSuccess,
|
||||
}: {
|
||||
onSuccess?: () => void
|
||||
}) => {
|
||||
return useMutation({
|
||||
mutationKey: [NAME_SPACE, 'remove-provider-credentials'],
|
||||
mutationFn: (providerName: string) => {
|
||||
return post(`/workspaces/current/tool-provider/builtin/${providerName}/delete`, {
|
||||
body: {},
|
||||
})
|
||||
},
|
||||
onSuccess,
|
||||
})
|
||||
}
|
||||
|
|
@ -1,9 +1,20 @@
|
|||
import { useQuery } from '@tanstack/react-query'
|
||||
import { get } from './base'
|
||||
import type {
|
||||
FetchWorkflowDraftResponse,
|
||||
} from '@/types/workflow'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import type { WorkflowConfigResponse } from '@/types/workflow'
|
||||
|
||||
const NAME_SPACE = 'workflow'
|
||||
|
||||
export const useAppWorkflow = (appID: string) => {
|
||||
return useQuery<FetchWorkflowDraftResponse>({
|
||||
enabled: !!appID,
|
||||
queryKey: [NAME_SPACE, 'publish', appID],
|
||||
queryFn: () => get<FetchWorkflowDraftResponse>(`/apps/${appID}/workflows/publish`),
|
||||
})
|
||||
}
|
||||
|
||||
export const useWorkflowConfig = (appId: string) => {
|
||||
return useQuery({
|
||||
queryKey: [NAME_SPACE, 'config', appId],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue