refactor: Remove Serpapi plugin integration and related tests

This commit is contained in:
twwu
2026-05-25 14:54:41 +08:00
parent f5c49231f1
commit 0d238a3e20
33 changed files with 0 additions and 645 deletions

View File

@ -1,69 +0,0 @@
import type { Form, ValidateValue } from '../key-validator/declarations'
import type { PluginProvider } from '@/models/common'
import { toast } from '@langgenius/dify-ui/toast'
import { useTranslation } from 'react-i18next'
import { useAppContext } from '@/context/app-context'
import SerpapiLogo from '../../assets/serpapi.png'
import KeyValidator from '../key-validator'
import { updatePluginKey, validatePluginKey } from './utils'
type SerpapiPluginProps = {
plugin: PluginProvider
onUpdate: () => void
}
const SerpapiPlugin = ({ plugin, onUpdate }: SerpapiPluginProps) => {
const { t } = useTranslation()
const { isCurrentWorkspaceManager } = useAppContext()
const forms: Form[] = [{
key: 'api_key',
title: t('plugin.serpapi.apiKey', { ns: 'common' }),
placeholder: t('plugin.serpapi.apiKeyPlaceholder', { ns: 'common' }),
value: plugin.credentials?.api_key,
validate: {
before: (v) => {
if (v?.api_key)
return true
},
run: async (v) => {
return validatePluginKey('serpapi', {
credentials: {
api_key: v?.api_key,
},
})
},
},
handleFocus: (v, dispatch) => {
if (v.api_key === plugin.credentials?.api_key)
dispatch({ ...v, api_key: '' })
},
}]
const handleSave = async (v: ValidateValue) => {
if (!v?.api_key || v?.api_key === plugin.credentials?.api_key)
return
const res = await updatePluginKey('serpapi', {
credentials: {
api_key: v?.api_key,
},
})
if (res.status === 'success') {
toast.success(t('actionMsg.modifiedSuccessfully', { ns: 'common' }))
onUpdate()
return true
}
}
return (
<KeyValidator
type="serpapi"
title={<img alt="serpapi logo" src={SerpapiLogo.src} width={64} />}
status={plugin.credentials?.api_key ? 'success' : 'add'}
forms={forms}
keyFrom={{
text: t('plugin.serpapi.keyFrom', { ns: 'common' }),
link: 'https://serpapi.com/manage-api-key',
}}
onSave={handleSave}
disabled={!isCurrentWorkspaceManager}
/>
)
}
export default SerpapiPlugin

View File

@ -1,213 +0,0 @@
import type { PluginProvider } from '@/models/common'
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { useAppContext } from '@/context/app-context'
import SerpapiPlugin from '../SerpapiPlugin'
import { updatePluginKey, validatePluginKey } from '../utils'
const mockEventEmitter = vi.hoisted(() => {
let subscriber: ((value: string) => void) | undefined
return {
useSubscription: vi.fn((callback: (value: string) => void) => {
subscriber = callback
}),
emit: vi.fn((value: string) => {
subscriber?.(value)
}),
reset: () => {
subscriber = undefined
},
}
})
const { mockToast } = vi.hoisted(() => {
const mockToast = Object.assign(vi.fn(), {
success: vi.fn(),
error: vi.fn(),
warning: vi.fn(),
info: vi.fn(),
dismiss: vi.fn(),
update: vi.fn(),
promise: vi.fn(),
})
return { mockToast }
})
vi.mock('@langgenius/dify-ui/toast', () => ({
toast: mockToast,
}))
vi.mock('@/context/app-context', () => ({
useAppContext: vi.fn(),
}))
vi.mock('../utils', () => ({
updatePluginKey: vi.fn(),
validatePluginKey: vi.fn(),
}))
vi.mock('@/context/event-emitter', () => ({
useEventEmitterContextContext: vi.fn(() => ({
eventEmitter: mockEventEmitter,
})),
}))
describe('SerpapiPlugin', () => {
const mockOnUpdate = vi.fn()
const mockUpdatePluginKey = updatePluginKey as ReturnType<typeof vi.fn>
const mockValidatePluginKey = validatePluginKey as ReturnType<typeof vi.fn>
beforeEach(() => {
vi.clearAllMocks()
mockEventEmitter.reset()
const mockUseAppContext = useAppContext as ReturnType<typeof vi.fn>
mockUseAppContext.mockReturnValue({
isCurrentWorkspaceManager: true,
})
mockValidatePluginKey.mockResolvedValue({ status: 'success' })
mockUpdatePluginKey.mockResolvedValue({ status: 'success' })
})
it('should show key input when manager clicks edit key', () => {
const mockPlugin: PluginProvider = {
tool_name: 'serpapi',
credentials: {
api_key: 'existing-key',
},
} as PluginProvider
render(<SerpapiPlugin plugin={mockPlugin} onUpdate={mockOnUpdate} />)
fireEvent.click(screen.getByText('common.provider.editKey'))
expect(screen.getByPlaceholderText('common.plugin.serpapi.apiKeyPlaceholder')).toBeInTheDocument()
})
it('should clear existing key on focus and show validation error for invalid key', async () => {
vi.useFakeTimers()
try {
mockValidatePluginKey.mockResolvedValue({ status: 'error', message: 'Invalid API key' })
const mockPlugin: PluginProvider = {
tool_name: 'serpapi',
credentials: {
api_key: 'existing-key',
},
} as PluginProvider
render(<SerpapiPlugin plugin={mockPlugin} onUpdate={mockOnUpdate} />)
fireEvent.click(screen.getByText('common.provider.editKey'))
const input = screen.getByPlaceholderText('common.plugin.serpapi.apiKeyPlaceholder')
expect(input).toHaveValue('existing-key')
fireEvent.focus(input)
expect(input).toHaveValue('')
fireEvent.change(input, {
target: { value: 'invalid-key' },
})
await act(async () => {
await vi.advanceTimersByTimeAsync(1000)
})
expect(screen.getByText(/Invalid API key/)).toBeInTheDocument()
fireEvent.focus(input)
expect(input).toHaveValue('invalid-key')
fireEvent.change(input, {
target: { value: '' },
})
await act(async () => {
await vi.advanceTimersByTimeAsync(1000)
})
expect(screen.queryByText(/Invalid API key/)).toBeNull()
}
finally {
vi.useRealTimers()
}
})
it('should not open key input when user is not workspace manager', () => {
const mockUseAppContext = useAppContext as ReturnType<typeof vi.fn>
mockUseAppContext.mockReturnValue({
isCurrentWorkspaceManager: false,
})
const mockPlugin = {
tool_name: 'serpapi',
is_enabled: true,
credentials: null,
} satisfies PluginProvider
render(<SerpapiPlugin plugin={mockPlugin} onUpdate={mockOnUpdate} />)
fireEvent.click(screen.getByText('common.provider.addKey'))
expect(screen.queryByPlaceholderText('common.plugin.serpapi.apiKeyPlaceholder')).toBeNull()
})
it('should save changed key and trigger success feedback', async () => {
const mockPlugin: PluginProvider = {
tool_name: 'serpapi',
credentials: {
api_key: 'existing-key',
},
} as PluginProvider
render(<SerpapiPlugin plugin={mockPlugin} onUpdate={mockOnUpdate} />)
fireEvent.click(screen.getByText('common.provider.editKey'))
fireEvent.change(screen.getByPlaceholderText('common.plugin.serpapi.apiKeyPlaceholder'), {
target: { value: 'new-key' },
})
fireEvent.click(screen.getByText('common.operation.save'))
await waitFor(() => {
expect(screen.queryByPlaceholderText('common.plugin.serpapi.apiKeyPlaceholder')).toBeNull()
})
})
it('should keep editor open when save request fails', async () => {
mockUpdatePluginKey.mockResolvedValue({ status: 'error', message: 'update failed' })
const mockPlugin: PluginProvider = {
tool_name: 'serpapi',
credentials: {
api_key: 'existing-key',
},
} as PluginProvider
render(<SerpapiPlugin plugin={mockPlugin} onUpdate={mockOnUpdate} />)
fireEvent.click(screen.getByText('common.provider.editKey'))
fireEvent.change(screen.getByPlaceholderText('common.plugin.serpapi.apiKeyPlaceholder'), {
target: { value: 'new-key' },
})
fireEvent.click(screen.getByText('common.operation.save'))
await waitFor(() => {
expect(screen.getByPlaceholderText('common.plugin.serpapi.apiKeyPlaceholder')).toBeInTheDocument()
})
})
it('should keep editor open when key value is unchanged', async () => {
const mockPlugin: PluginProvider = {
tool_name: 'serpapi',
credentials: {
api_key: 'existing-key',
},
} as PluginProvider
render(<SerpapiPlugin plugin={mockPlugin} onUpdate={mockOnUpdate} />)
fireEvent.click(screen.getByText('common.provider.editKey'))
fireEvent.click(screen.getByText('common.operation.save'))
await waitFor(() => {
expect(screen.getByPlaceholderText('common.plugin.serpapi.apiKeyPlaceholder')).toBeInTheDocument()
})
})
})

View File

@ -1,120 +0,0 @@
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { useState } from 'react'
import { useAppContext } from '@/context/app-context'
import PluginPage from '../index'
import { updatePluginKey, validatePluginKey } from '../utils'
const mockUsePluginProviders = vi.hoisted(() => vi.fn())
vi.mock('@/service/use-common', () => ({
usePluginProviders: mockUsePluginProviders,
}))
vi.mock('@/context/app-context', () => ({
useAppContext: vi.fn(),
}))
vi.mock('@langgenius/dify-ui/toast', async (importOriginal) => {
const actual = await importOriginal<typeof import('@langgenius/dify-ui/toast')>()
return {
...actual,
}
})
vi.mock('@/context/event-emitter', () => ({
useEventEmitterContextContext: () => ({
eventEmitter: {
emit: vi.fn(),
useSubscription: vi.fn(),
},
}),
}))
vi.mock('../utils', () => ({
updatePluginKey: vi.fn(),
validatePluginKey: vi.fn(),
}))
describe('PluginPage', () => {
const mockUpdatePluginKey = updatePluginKey as ReturnType<typeof vi.fn>
const mockValidatePluginKey = validatePluginKey as ReturnType<typeof vi.fn>
beforeEach(() => {
vi.clearAllMocks()
const mockUseAppContext = useAppContext as ReturnType<typeof vi.fn>
mockUseAppContext.mockReturnValue({
isCurrentWorkspaceManager: true,
})
mockValidatePluginKey.mockResolvedValue({ status: 'success' })
mockUpdatePluginKey.mockResolvedValue({ status: 'success' })
})
it('should render plugin settings with edit action when serpapi key exists', () => {
mockUsePluginProviders.mockReturnValue({
data: [
{ tool_name: 'serpapi', credentials: { api_key: 'test-key' } },
],
refetch: vi.fn(),
})
render(<PluginPage />)
expect(screen.getByText('common.provider.editKey')).toBeInTheDocument()
})
it('should render plugin settings with add action when serpapi key is missing', () => {
mockUsePluginProviders.mockReturnValue({
data: [
{ tool_name: 'serpapi', credentials: null },
],
refetch: vi.fn(),
})
render(<PluginPage />)
expect(screen.getByText('common.provider.addKey')).toBeInTheDocument()
})
it('should display encryption notice with PKCS1_OAEP link', () => {
mockUsePluginProviders.mockReturnValue({
data: [],
refetch: vi.fn(),
})
render(<PluginPage />)
expect(screen.getByText(/common\.provider\.encrypted\.front/)).toBeInTheDocument()
expect(screen.getByText(/common\.provider\.encrypted\.back/)).toBeInTheDocument()
const link = screen.getByRole('link', { name: 'PKCS1_OAEP' })
expect(link).toHaveAttribute('target', '_blank')
expect(link).toHaveAttribute('href', 'https://pycryptodome.readthedocs.io/en/latest/src/cipher/oaep.html')
})
it('should show reload state after saving key', async () => {
let showReloadedState = () => {}
const Wrapper = () => {
const [reloaded, setReloaded] = useState(false)
showReloadedState = () => setReloaded(true)
return (
<>
<PluginPage />
{reloaded && <div>providers-reloaded</div>}
</>
)
}
mockUsePluginProviders.mockImplementation(() => ({
data: [{ tool_name: 'serpapi', credentials: { api_key: 'existing-key' } }],
refetch: () => showReloadedState(),
}))
render(<Wrapper />)
fireEvent.click(screen.getByText('common.provider.editKey'))
fireEvent.change(screen.getByPlaceholderText('common.plugin.serpapi.apiKeyPlaceholder'), {
target: { value: 'new-key' },
})
fireEvent.click(screen.getByText('common.operation.save'))
await waitFor(() => {
expect(screen.getByText('providers-reloaded')).toBeInTheDocument()
})
})
})

View File

@ -1,73 +0,0 @@
import { updatePluginProviderAIKey, validatePluginProviderKey } from '@/service/common'
import { ValidatedStatus } from '../../key-validator/declarations'
import { updatePluginKey, validatePluginKey } from '../utils'
vi.mock('@/service/common', () => ({
validatePluginProviderKey: vi.fn(),
updatePluginProviderAIKey: vi.fn(),
}))
const mockValidatePluginProviderKey = validatePluginProviderKey as ReturnType<typeof vi.fn>
const mockUpdatePluginProviderAIKey = updatePluginProviderAIKey as ReturnType<typeof vi.fn>
describe('Plugin Utils', () => {
beforeEach(() => {
vi.clearAllMocks()
})
describe.each([
{
name: 'validatePluginKey',
utilFn: validatePluginKey,
serviceMock: mockValidatePluginProviderKey,
successBody: { credentials: { api_key: 'test-key' } },
failureBody: { credentials: { api_key: 'invalid' } },
exceptionBody: { credentials: { api_key: 'test' } },
serviceErrorMessage: 'Invalid API key',
thrownErrorMessage: 'Network error',
},
{
name: 'updatePluginKey',
utilFn: updatePluginKey,
serviceMock: mockUpdatePluginProviderAIKey,
successBody: { credentials: { api_key: 'new-key' } },
failureBody: { credentials: { api_key: 'test' } },
exceptionBody: { credentials: { api_key: 'test' } },
serviceErrorMessage: 'Update failed',
thrownErrorMessage: 'Request failed',
},
])('$name', ({ utilFn, serviceMock, successBody, failureBody, exceptionBody, serviceErrorMessage, thrownErrorMessage }) => {
it('should return success status when service succeeds', async () => {
serviceMock.mockResolvedValue({ result: 'success' })
const result = await utilFn('serpapi', successBody)
expect(result.status).toBe(ValidatedStatus.Success)
})
it('should return error status with message when service returns an error', async () => {
serviceMock.mockResolvedValue({
result: 'error',
error: serviceErrorMessage,
})
const result = await utilFn('serpapi', failureBody)
expect(result).toMatchObject({
status: ValidatedStatus.Error,
message: serviceErrorMessage,
})
})
it('should return error status when service throws exception', async () => {
serviceMock.mockRejectedValue(new Error(thrownErrorMessage))
const result = await utilFn('serpapi', exceptionBody)
expect(result).toMatchObject({
status: ValidatedStatus.Error,
message: thrownErrorMessage,
})
})
})
})

View File

@ -1,38 +0,0 @@
import type { PluginProvider } from '@/models/common'
import { LockClosedIcon } from '@heroicons/react/24/solid'
import { useTranslation } from 'react-i18next'
import Link from '@/next/link'
import { usePluginProviders } from '@/service/use-common'
import SerpapiPlugin from './SerpapiPlugin'
const PluginPage = () => {
const { t } = useTranslation()
const { data: plugins, refetch: mutate } = usePluginProviders()
const Plugin_MAP: Record<string, (plugin: PluginProvider) => React.JSX.Element> = {
serpapi: (plugin: PluginProvider) => <SerpapiPlugin key="serpapi" plugin={plugin} onUpdate={() => mutate()} />,
}
return (
<div className="pb-7">
<div>
{plugins?.map(plugin => Plugin_MAP[plugin.tool_name]!(plugin))}
</div>
<div className="fixed bottom-0 flex h-[42px] w-[472px] items-center bg-white text-xs text-gray-500">
<LockClosedIcon className="mr-1 size-3" />
{t('provider.encrypted.front', { ns: 'common' })}
<Link
className="mx-1 text-primary-600"
target="_blank"
rel="noopener noreferrer"
href="https://pycryptodome.readthedocs.io/en/latest/src/cipher/oaep.html"
>
PKCS1_OAEP
</Link>
{t('provider.encrypted.back', { ns: 'common' })}
</div>
</div>
)
}
export default PluginPage

View File

@ -1,34 +0,0 @@
import { updatePluginProviderAIKey, validatePluginProviderKey } from '@/service/common'
import { ValidatedStatus } from '../key-validator/declarations'
export const validatePluginKey = async (pluginType: string, body: any) => {
try {
const res = await validatePluginProviderKey({
url: `/workspaces/current/tool-providers/${pluginType}/credentials-validate`,
body,
})
if (res.result === 'success')
return Promise.resolve({ status: ValidatedStatus.Success })
else
return Promise.resolve({ status: ValidatedStatus.Error, message: res.error })
}
catch (e: any) {
return Promise.resolve({ status: ValidatedStatus.Error, message: e.message })
}
}
export const updatePluginKey = async (pluginType: string, body: any) => {
try {
const res = await updatePluginProviderAIKey({
url: `/workspaces/current/tool-providers/${pluginType}/credentials`,
body,
})
if (res.result === 'success')
return Promise.resolve({ status: ValidatedStatus.Success })
else
return Promise.resolve({ status: ValidatedStatus.Error, message: res.error })
}
catch (e: any) {
return Promise.resolve({ status: ValidatedStatus.Error, message: e.message })
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -538,9 +538,6 @@
"placeholder.input": "يرجى الإدخال",
"placeholder.search": "بحث...",
"placeholder.select": "يرجى التحديد",
"plugin.serpapi.apiKey": "مفتاح API",
"plugin.serpapi.apiKeyPlaceholder": "أدخل مفتاح API الخاص بك",
"plugin.serpapi.keyFrom": "احصل على مفتاح SerpAPI الخاص بك من صفحة حساب SerpAPI",
"promptEditor.context.item.desc": "إدراج قالب السياق",
"promptEditor.context.item.title": "السياق",
"promptEditor.context.modal.add": "إضافة سياق ",

View File

@ -538,9 +538,6 @@
"placeholder.input": "Bitte eingeben",
"placeholder.search": "Suchen...",
"placeholder.select": "Bitte auswählen",
"plugin.serpapi.apiKey": "API-Schlüssel",
"plugin.serpapi.apiKeyPlaceholder": "Geben Sie Ihren API-Schlüssel ein",
"plugin.serpapi.keyFrom": "Holen Sie Ihren SerpAPI-Schlüssel von der SerpAPI-Kontoseite",
"promptEditor.context.item.desc": "Kontextvorlage einfügen",
"promptEditor.context.item.title": "Kontext",
"promptEditor.context.modal.add": "Kontext hinzufügen",

View File

@ -569,9 +569,6 @@
"placeholder.input": "Please enter",
"placeholder.search": "Search...",
"placeholder.select": "Please select",
"plugin.serpapi.apiKey": "API Key",
"plugin.serpapi.apiKeyPlaceholder": "Enter your API key",
"plugin.serpapi.keyFrom": "Get your SerpAPI key from SerpAPI Account Page",
"promptEditor.context.item.desc": "Insert context template",
"promptEditor.context.item.title": "Context",
"promptEditor.context.modal.add": "Add Context ",

View File

@ -538,9 +538,6 @@
"placeholder.input": "Por favor ingresa",
"placeholder.search": "Buscar...",
"placeholder.select": "Por favor selecciona",
"plugin.serpapi.apiKey": "Clave API",
"plugin.serpapi.apiKeyPlaceholder": "Ingresa tu clave API",
"plugin.serpapi.keyFrom": "Obtén tu clave API de SerpAPI en la página de cuenta de SerpAPI",
"promptEditor.context.item.desc": "Insertar plantilla de contexto",
"promptEditor.context.item.title": "Contexto",
"promptEditor.context.modal.add": "Agregar Contexto ",

View File

@ -538,9 +538,6 @@
"placeholder.input": "لطفا وارد کنید",
"placeholder.search": "جستجو...",
"placeholder.select": "لطفا انتخاب کنید",
"plugin.serpapi.apiKey": "کلید API",
"plugin.serpapi.apiKeyPlaceholder": "کلید API خود را وارد کنید",
"plugin.serpapi.keyFrom": "کلید SerpAPI خود را از صفحه حساب SerpAPI دریافت کنید",
"promptEditor.context.item.desc": "درج الگوی زمینه",
"promptEditor.context.item.title": "زمینه",
"promptEditor.context.modal.add": "افزودن زمینه",

View File

@ -538,9 +538,6 @@
"placeholder.input": "Veuillez entrer",
"placeholder.search": "Rechercher...",
"placeholder.select": "Veuillez sélectionner",
"plugin.serpapi.apiKey": "Clé API",
"plugin.serpapi.apiKeyPlaceholder": "Entrez votre clé API",
"plugin.serpapi.keyFrom": "Obtenez votre clé SerpAPI depuis la page de compte SerpAPI",
"promptEditor.context.item.desc": "Insérez le modèle de contexte",
"promptEditor.context.item.title": "Contexte",
"promptEditor.context.modal.add": "Ajouter Contexte",

View File

@ -538,9 +538,6 @@
"placeholder.input": "कृपया दर्ज करें",
"placeholder.search": "खोजें...",
"placeholder.select": "कृपया चयन करें",
"plugin.serpapi.apiKey": "एपीआई कुंजी",
"plugin.serpapi.apiKeyPlaceholder": "अपनी एपीआई कुंजी दर्ज करें",
"plugin.serpapi.keyFrom": "SerpAPI खाता पृष्ठ से अपनी SerpAPI कुंजी प्राप्त करें",
"promptEditor.context.item.desc": "संदर्भ टेम्पलेट डालें",
"promptEditor.context.item.title": "संदर्भ",
"promptEditor.context.modal.add": "संदर्भ जोड़ें",

View File

@ -538,9 +538,6 @@
"placeholder.input": "Silakan masuk",
"placeholder.search": "Cari...",
"placeholder.select": "Silakan pilih",
"plugin.serpapi.apiKey": "Kunci API",
"plugin.serpapi.apiKeyPlaceholder": "Masukkan kunci API Anda",
"plugin.serpapi.keyFrom": "Dapatkan kunci SerpAPI Anda dari Halaman Akun SerpAPI",
"promptEditor.context.item.desc": "Sisipkan templat konteks",
"promptEditor.context.item.title": "Konteks",
"promptEditor.context.modal.add": "Tambahkan Konteks",

View File

@ -538,9 +538,6 @@
"placeholder.input": "Per favore inserisci",
"placeholder.search": "Cerca...",
"placeholder.select": "Per favore seleziona",
"plugin.serpapi.apiKey": "API Key",
"plugin.serpapi.apiKeyPlaceholder": "Inserisci la tua API key",
"plugin.serpapi.keyFrom": "Ottieni la tua API key dalla pagina dell'account SerpAPI",
"promptEditor.context.item.desc": "Inserisci modello di contesto",
"promptEditor.context.item.title": "Contesto",
"promptEditor.context.modal.add": "Aggiungi Contesto ",

View File

@ -569,9 +569,6 @@
"placeholder.input": "入力してください",
"placeholder.search": "検索...",
"placeholder.select": "選択してください",
"plugin.serpapi.apiKey": "API キー",
"plugin.serpapi.apiKeyPlaceholder": "API キーを入力してください",
"plugin.serpapi.keyFrom": "SerpAPI アカウントページから SerpAPI キーを取得してください",
"promptEditor.context.item.desc": "コンテキストテンプレートを挿入",
"promptEditor.context.item.title": "コンテキスト",
"promptEditor.context.modal.add": "コンテキストを追加",

View File

@ -538,9 +538,6 @@
"placeholder.input": "입력해주세요",
"placeholder.search": "검색...",
"placeholder.select": "선택해주세요",
"plugin.serpapi.apiKey": "API 키",
"plugin.serpapi.apiKeyPlaceholder": "API 키를 입력하세요",
"plugin.serpapi.keyFrom": "SerpAPI 계정 페이지에서 SerpAPI 키를 가져오세요",
"promptEditor.context.item.desc": "컨텍스트 템플릿을 삽입합니다.",
"promptEditor.context.item.title": "컨텍스트",
"promptEditor.context.modal.add": "컨텍스트 추가",

View File

@ -538,9 +538,6 @@
"placeholder.input": "Please enter",
"placeholder.search": "Search...",
"placeholder.select": "Please select",
"plugin.serpapi.apiKey": "API Key",
"plugin.serpapi.apiKeyPlaceholder": "Enter your API key",
"plugin.serpapi.keyFrom": "Get your SerpAPI key from SerpAPI Account Page",
"promptEditor.context.item.desc": "Insert context template",
"promptEditor.context.item.title": "Context",
"promptEditor.context.modal.add": "Add Context ",

View File

@ -538,9 +538,6 @@
"placeholder.input": "Proszę wprowadzić",
"placeholder.search": "Szukaj...",
"placeholder.select": "Proszę wybrać",
"plugin.serpapi.apiKey": "Klucz API",
"plugin.serpapi.apiKeyPlaceholder": "Wprowadź swój klucz API",
"plugin.serpapi.keyFrom": "Pobierz swój klucz SerpAPI ze strony konta SerpAPI",
"promptEditor.context.item.desc": "Wstaw szablon kontekstu",
"promptEditor.context.item.title": "Kontekst",
"promptEditor.context.modal.add": "Dodaj Kontekst ",

View File

@ -538,9 +538,6 @@
"placeholder.input": "Por favor, insira",
"placeholder.search": "Pesquisar...",
"placeholder.select": "Por favor, selecione",
"plugin.serpapi.apiKey": "Chave da API",
"plugin.serpapi.apiKeyPlaceholder": "Insira sua chave da API",
"plugin.serpapi.keyFrom": "Obtenha sua chave da SerpAPI na página da conta da SerpAPI",
"promptEditor.context.item.desc": "Inserir modelo de contexto",
"promptEditor.context.item.title": "Contexto",
"promptEditor.context.modal.add": "Adicionar Contexto",

View File

@ -538,9 +538,6 @@
"placeholder.input": "Vă rugăm să introduceți",
"placeholder.search": "Caută...",
"placeholder.select": "Vă rugăm să selectați",
"plugin.serpapi.apiKey": "Cheie API",
"plugin.serpapi.apiKeyPlaceholder": "Introduceți cheia dvs. API",
"plugin.serpapi.keyFrom": "Obțineți cheia dvs. SerpAPI din pagina contului SerpAPI",
"promptEditor.context.item.desc": "Inserați șablon de context",
"promptEditor.context.item.title": "Context",
"promptEditor.context.modal.add": "Adăugați context ",

View File

@ -538,9 +538,6 @@
"placeholder.input": "Пожалуйста, введите",
"placeholder.search": "Поиск...",
"placeholder.select": "Пожалуйста, выберите",
"plugin.serpapi.apiKey": "Ключ API",
"plugin.serpapi.apiKeyPlaceholder": "Введите свой ключ API",
"plugin.serpapi.keyFrom": "Получите свой ключ SerpAPI на странице учетной записи SerpAPI",
"promptEditor.context.item.desc": "Вставить шаблон контекста",
"promptEditor.context.item.title": "Контекст",
"promptEditor.context.modal.add": "Добавить контекст ",

View File

@ -538,9 +538,6 @@
"placeholder.input": "Vnesite prosim",
"placeholder.search": "Išči...",
"placeholder.select": "Izberite prosim",
"plugin.serpapi.apiKey": "API ključ",
"plugin.serpapi.apiKeyPlaceholder": "Vnesite ključ API",
"plugin.serpapi.keyFrom": "Pridobite svoj ključ SerpAPI na strani računa SerpAPI",
"promptEditor.context.item.desc": "Vstavljanje predloge konteksta",
"promptEditor.context.item.title": "Kontekstu",
"promptEditor.context.modal.add": "Dodajanje konteksta",

View File

@ -538,9 +538,6 @@
"placeholder.input": "กรุณากรอก",
"placeholder.search": "ค้นหา...",
"placeholder.select": "กรุณาเลือก",
"plugin.serpapi.apiKey": "คีย์ API",
"plugin.serpapi.apiKeyPlaceholder": "ป้อนคีย์ API ของคุณ",
"plugin.serpapi.keyFrom": "รับคีย์ SerpAPI ของคุณจากหน้าบัญชี SerpAPI",
"promptEditor.context.item.desc": "แทรกเทมเพลตบริบท",
"promptEditor.context.item.title": "บริบท",
"promptEditor.context.modal.add": "เพิ่มบริบท",

View File

@ -538,9 +538,6 @@
"placeholder.input": "Lütfen girin",
"placeholder.search": "Ara...",
"placeholder.select": "Lütfen seçin",
"plugin.serpapi.apiKey": "API Anahtarı",
"plugin.serpapi.apiKeyPlaceholder": "API anahtarınızı girin",
"plugin.serpapi.keyFrom": "SerpAPI Hesap Sayfasından SerpAPI anahtarınızı alın",
"promptEditor.context.item.desc": "Bağlam şablonunu ekle",
"promptEditor.context.item.title": "Bağlam",
"promptEditor.context.modal.add": "Bağlam Ekle",

View File

@ -538,9 +538,6 @@
"placeholder.input": "Будь ласка, введіть текст",
"placeholder.search": "Пошук...",
"placeholder.select": "Будь ласка, оберіть параметр",
"plugin.serpapi.apiKey": "Ключ API",
"plugin.serpapi.apiKeyPlaceholder": "Введіть свій ключ API",
"plugin.serpapi.keyFrom": "Отримайте свій ключ SerpAPI зі сторінки облікового запису SerpAPI",
"promptEditor.context.item.desc": "Вставити шаблон контексту",
"promptEditor.context.item.title": "Контекст",
"promptEditor.context.modal.add": "Додати контекст",

View File

@ -538,9 +538,6 @@
"placeholder.input": "Vui lòng nhập",
"placeholder.search": "Tìm kiếm...",
"placeholder.select": "Vui lòng chọn",
"plugin.serpapi.apiKey": "Khóa API",
"plugin.serpapi.apiKeyPlaceholder": "Nhập khóa API của bạn",
"plugin.serpapi.keyFrom": "Nhận khóa SerpAPI của bạn từ Trang tài khoản SerpAPI",
"promptEditor.context.item.desc": "Chèn mẫu bối cảnh",
"promptEditor.context.item.title": "Bối cảnh",
"promptEditor.context.modal.add": "Thêm Bối cảnh",

View File

@ -569,9 +569,6 @@
"placeholder.input": "请输入",
"placeholder.search": "搜索...",
"placeholder.select": "请选择",
"plugin.serpapi.apiKey": "API Key",
"plugin.serpapi.apiKeyPlaceholder": "输入你的 API 密钥",
"plugin.serpapi.keyFrom": "从 SerpAPI 帐户页面获取您的 SerpAPI 密钥",
"promptEditor.context.item.desc": "插入上下文模板",
"promptEditor.context.item.title": "上下文",
"promptEditor.context.modal.add": "添加上下文",

View File

@ -538,9 +538,6 @@
"placeholder.input": "請輸入",
"placeholder.search": "搜尋...",
"placeholder.select": "請選擇",
"plugin.serpapi.apiKey": "API Key",
"plugin.serpapi.apiKeyPlaceholder": "輸入你的 API 金鑰",
"plugin.serpapi.keyFrom": "從 SerpAPI 帳戶頁面獲取您的 SerpAPI 金鑰",
"promptEditor.context.item.desc": "插入上下文模板",
"promptEditor.context.item.title": "上下文",
"promptEditor.context.modal.add": "新增上下文",

View File

@ -159,14 +159,6 @@ export enum DataSourceProvider {
waterCrawl = 'watercrawl',
}
export type PluginProvider = {
tool_name: string
is_enabled: boolean
credentials: {
api_key: string
} | null
}
export type FileUploadConfigResponse = {
batch_count_limit: number
image_file_size_limit?: number | string // default is 10MB

View File

@ -25,7 +25,6 @@ import type {
Member,
ModerateResponse,
OauthResponse,
PluginProvider,
Provider,
ProviderAnthropicToken,
ProviderAzureToken,
@ -165,17 +164,6 @@ export const updateDataSourceNotionAction = ({ url }: { url: string }): Promise<
return patch<CommonResponse>(url)
}
export const fetchPluginProviders = (url: string): Promise<PluginProvider[] | null> => {
return get<PluginProvider[] | null>(url)
}
export const validatePluginProviderKey = ({ url, body }: { url: string, body: { credentials: any } }): Promise<ValidateOpenAIKeyResponse> => {
return post<ValidateOpenAIKeyResponse>(url, { body })
}
export const updatePluginProviderAIKey = ({ url, body }: { url: string, body: { credentials: any } }): Promise<UpdateOpenAIKeyResponse> => {
return post<UpdateOpenAIKeyResponse>(url, { body })
}
export const invitationCheck = ({ url, params }: { url: string, params: { workspace_id?: string, email?: string, token: string } }): Promise<CommonResponse & { is_valid: boolean, data: { workspace_name: string, email: string, workspace_id: string } }> => {
return get<CommonResponse & { is_valid: boolean, data: { workspace_name: string, email: string, workspace_id: string } }>(url, { params })
}

View File

@ -14,7 +14,6 @@ import type {
IWorkspace,
LangGeniusVersionResponse,
Member,
PluginProvider,
StructuredOutputRulesRequestBody,
StructuredOutputRulesResponse,
UserProfileResponse,
@ -49,7 +48,6 @@ export const commonQueryKeys = {
defaultModel: (type: ModelTypeEnum) => [NAME_SPACE, 'default-model', type] as const,
retrievalMethods: [NAME_SPACE, 'support-retrieval-methods'] as const,
accountIntegrates: [NAME_SPACE, 'account-integrates'] as const,
pluginProviders: [NAME_SPACE, 'plugin-providers'] as const,
notionConnection: [NAME_SPACE, 'notion-connection'] as const,
codeBasedExtensions: (module?: string) => [NAME_SPACE, 'code-based-extensions', module] as const,
invitationCheck: (params?: { workspace_id?: string, email?: string, token?: string }) => [
@ -303,13 +301,6 @@ export const useAccountIntegrates = () => {
})
}
export const usePluginProviders = () => {
return useQuery<PluginProvider[] | null>({
queryKey: commonQueryKeys.pluginProviders,
queryFn: () => get<PluginProvider[] | null>('/workspaces/current/tool-providers'),
})
}
export const useCodeBasedExtensions = (module: string) => {
return useQuery<CodeBasedExtension>({
queryKey: commonQueryKeys.codeBasedExtensions(module),