> = ({
modelId: string
mode?: string
}) => {
- handleCompletionParamsChange({})
- handleModelChanged(model)
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [])
+ (async () => {
+ try {
+ const { params: filtered, removedDetails } = await fetchAndMergeValidCompletionParams(
+ model.provider,
+ model.modelId,
+ inputs.model.completion_params,
+ )
+ const keys = Object.keys(removedDetails)
+ if (keys.length)
+ Toast.notify({ type: 'warning', message: `${t('common.modelProvider.parametersInvalidRemoved')}: ${keys.map(k => `${k} (${removedDetails[k]})`).join(', ')}` })
+ handleCompletionParamsChange(filtered)
+ }
+ catch (e) {
+ Toast.notify({ type: 'error', message: t('common.error') })
+ handleCompletionParamsChange({})
+ }
+ finally {
+ handleModelChanged(model)
+ }
+ })()
+ }, [inputs.model.completion_params])
return (
diff --git a/web/app/components/workflow/types.ts b/web/app/components/workflow/types.ts
index 19b0f6db77..f88519dd41 100644
--- a/web/app/components/workflow/types.ts
+++ b/web/app/components/workflow/types.ts
@@ -137,6 +137,7 @@ export type Variable = {
variable: string
}
value_selector: ValueSelector
+ value_type?: VarType
variable_type?: VarKindType
value?: string
options?: string[]
diff --git a/web/hooks/use-tab-searchparams.ts b/web/hooks/use-tab-searchparams.ts
index 0c0e3b7773..444944f812 100644
--- a/web/hooks/use-tab-searchparams.ts
+++ b/web/hooks/use-tab-searchparams.ts
@@ -29,9 +29,10 @@ export const useTabSearchParams = ({
const router = useRouter()
const pathName = pathnameFromHook || window?.location?.pathname
const searchParams = useSearchParams()
+ const searchParamValue = searchParams.has(searchParamName) ? decodeURIComponent(searchParams.get(searchParamName)!) : defaultTab
const [activeTab, setTab] = useState(
!disableSearchParams
- ? (searchParams.get(searchParamName) || defaultTab)
+ ? searchParamValue
: defaultTab,
)
@@ -39,7 +40,7 @@ export const useTabSearchParams = ({
setTab(newActiveTab)
if (disableSearchParams)
return
- router[`${routingBehavior}`](`${pathName}?${searchParamName}=${newActiveTab}`)
+ router[`${routingBehavior}`](`${pathName}?${searchParamName}=${encodeURIComponent(newActiveTab)}`)
}
return [activeTab, setActiveTab] as const
diff --git a/web/i18n/de-DE/dataset-documents.ts b/web/i18n/de-DE/dataset-documents.ts
index 22018f9da4..f52220a669 100644
--- a/web/i18n/de-DE/dataset-documents.ts
+++ b/web/i18n/de-DE/dataset-documents.ts
@@ -390,6 +390,8 @@ const translation = {
addChildChunk: 'Untergeordneten Block hinzufügen',
regenerationConfirmTitle: 'Möchten Sie untergeordnete Chunks regenerieren?',
searchResults_one: 'ERGEBNIS',
+ keywordEmpty: 'Das Schlüsselwort darf nicht leer sein.',
+ keywordDuplicate: 'Das Schlüsselwort existiert bereits',
},
}
diff --git a/web/i18n/en-US/app.ts b/web/i18n/en-US/app.ts
index e75a9d5358..1162a3d0aa 100644
--- a/web/i18n/en-US/app.ts
+++ b/web/i18n/en-US/app.ts
@@ -199,9 +199,9 @@ const translation = {
accessControl: 'Web App Access Control',
accessItemsDescription: {
anyone: 'Anyone can access the web app (no login required)',
- specific: 'Only specific members within the platform can access the Web application',
- organization: 'All members within the platform can access the Web application',
- external: 'Only authenticated external users can access the Web application',
+ specific: 'Only specific members within the platform can access the web app',
+ organization: 'All members within the platform can access the web app',
+ external: 'Only authenticated external users can access the web app',
},
accessControlDialog: {
title: 'Web App Access Control',
@@ -218,7 +218,7 @@ const translation = {
members_one: '{{count}} MEMBER',
members_other: '{{count}} MEMBERS',
noGroupsOrMembers: 'No groups or members selected',
- webAppSSONotEnabledTip: 'Please contact your organization administrator to configure external authentication for the Web application.',
+ webAppSSONotEnabledTip: 'Please contact your organization administrator to configure external authentication for the web app.',
operateGroupAndMember: {
searchPlaceholder: 'Search groups and members',
allMembers: 'All members',
diff --git a/web/i18n/en-US/common.ts b/web/i18n/en-US/common.ts
index f242ecd5a8..0823c6129c 100644
--- a/web/i18n/en-US/common.ts
+++ b/web/i18n/en-US/common.ts
@@ -456,6 +456,7 @@ const translation = {
connected: 'Connected',
disconnected: 'Disconnected',
changeAuthorizedPages: 'Change authorized pages',
+ integratedAlert: 'Notion is integrated via internal credential, no need to re-authorize.',
pagesAuthorized: 'Pages authorized',
sync: 'Sync',
remove: 'Remove',
diff --git a/web/i18n/en-US/workflow.ts b/web/i18n/en-US/workflow.ts
index 709ccca485..a18a39bd9f 100644
--- a/web/i18n/en-US/workflow.ts
+++ b/web/i18n/en-US/workflow.ts
@@ -555,6 +555,7 @@ const translation = {
advancedDependencies: 'Advanced Dependencies',
advancedDependenciesTip: 'Add some preloaded dependencies that take more time to consume or are not default built-in here',
searchDependencies: 'Search Dependencies',
+ syncFunctionSignature: 'Sync function signature to code',
},
templateTransform: {
inputVars: 'Input Variables',
diff --git a/web/i18n/es-ES/dataset-documents.ts b/web/i18n/es-ES/dataset-documents.ts
index cd5bb36197..53a6663847 100644
--- a/web/i18n/es-ES/dataset-documents.ts
+++ b/web/i18n/es-ES/dataset-documents.ts
@@ -389,6 +389,8 @@ const translation = {
characters_one: 'carácter',
regenerationSuccessMessage: 'Puede cerrar esta ventana.',
regenerationConfirmTitle: '¿Desea regenerar fragmentos secundarios?',
+ keywordEmpty: 'La palabra clave no puede estar vacía',
+ keywordDuplicate: 'La palabra clave ya existe',
},
}
diff --git a/web/i18n/fa-IR/dataset-documents.ts b/web/i18n/fa-IR/dataset-documents.ts
index 85e1e0a4aa..048cb5163f 100644
--- a/web/i18n/fa-IR/dataset-documents.ts
+++ b/web/i18n/fa-IR/dataset-documents.ts
@@ -388,6 +388,8 @@ const translation = {
regeneratingMessage: 'این ممکن است یک لحظه طول بکشد، لطفا صبر کنید...',
regenerationConfirmTitle: 'آیا می خواهید تکه های کودک را بازسازی کنید؟',
regenerationSuccessMessage: 'می توانید این پنجره را ببندید.',
+ keywordEmpty: 'کلمه کلیدی نمیتواند خالی باشد',
+ keywordDuplicate: 'این کلیدواژه قبلاً وجود دارد',
},
}
diff --git a/web/i18n/fr-FR/dataset-documents.ts b/web/i18n/fr-FR/dataset-documents.ts
index 7a795202ed..d8c0fe4af7 100644
--- a/web/i18n/fr-FR/dataset-documents.ts
+++ b/web/i18n/fr-FR/dataset-documents.ts
@@ -389,6 +389,8 @@ const translation = {
searchResults_zero: 'RÉSULTAT',
empty: 'Aucun Chunk trouvé',
editChildChunk: 'Modifier le morceau enfant',
+ keywordDuplicate: 'Le mot-clé existe déjà',
+ keywordEmpty: 'Le mot-clé ne peut pas être vide.',
},
}
diff --git a/web/i18n/hi-IN/dataset-documents.ts b/web/i18n/hi-IN/dataset-documents.ts
index 35bcb0aad2..1fcdd49449 100644
--- a/web/i18n/hi-IN/dataset-documents.ts
+++ b/web/i18n/hi-IN/dataset-documents.ts
@@ -390,6 +390,8 @@ const translation = {
chunkAdded: '1 हिस्सा जोड़ा गया',
chunkDetail: 'चंक विवरण',
regenerationConfirmMessage: 'चाइल्ड चंक्स को रीजनरेट करने से वर्तमान चाइल्ड चंक्स ओवरराइट हो जाएंगे, जिसमें संपादित चंक्स और नए जोड़े गए चंक्स शामिल हैं। पुनरुत्थान को पूर्ववत नहीं किया जा सकता है।',
+ keywordDuplicate: 'कीवर्ड पहले से मौजूद है',
+ keywordEmpty: 'कीवर्ड ख़ाली नहीं हो सकता',
},
}
diff --git a/web/i18n/it-IT/dataset-documents.ts b/web/i18n/it-IT/dataset-documents.ts
index b9afb1ea75..2881e1fcee 100644
--- a/web/i18n/it-IT/dataset-documents.ts
+++ b/web/i18n/it-IT/dataset-documents.ts
@@ -391,6 +391,8 @@ const translation = {
regenerationSuccessMessage: 'È possibile chiudere questa finestra.',
childChunkAdded: '1 blocco figlio aggiunto',
childChunks_other: 'BLOCCHI FIGLIO',
+ keywordEmpty: 'La parola chiave non può essere vuota',
+ keywordDuplicate: 'La parola chiave esiste già',
},
}
diff --git a/web/i18n/ja-JP/dataset-documents.ts b/web/i18n/ja-JP/dataset-documents.ts
index ecdbbf512c..e28425dc8f 100644
--- a/web/i18n/ja-JP/dataset-documents.ts
+++ b/web/i18n/ja-JP/dataset-documents.ts
@@ -388,6 +388,8 @@ const translation = {
editedAt: '編集日時',
expandChunks: 'チャンクを展開',
collapseChunks: 'チャンクを折りたたむ',
+ keywordDuplicate: 'そのキーワードは既に存在しています',
+ keywordEmpty: 'キーワードは空であってはいけません',
},
}
diff --git a/web/i18n/ja-JP/workflow.ts b/web/i18n/ja-JP/workflow.ts
index 5700d9c9b8..3c959669bf 100644
--- a/web/i18n/ja-JP/workflow.ts
+++ b/web/i18n/ja-JP/workflow.ts
@@ -550,6 +550,7 @@ const translation = {
advancedDependencies: '高度な依存関係',
advancedDependenciesTip: '消費に時間がかかる、またはデフォルトで組み込まれていない事前ロードされた依存関係を追加します',
searchDependencies: '依存関係を検索',
+ syncFunctionSignature: 'コードの関数署名を同期',
},
templateTransform: {
inputVars: '入力変数',
diff --git a/web/i18n/ko-KR/dataset-documents.ts b/web/i18n/ko-KR/dataset-documents.ts
index a379318959..ee94a880a0 100644
--- a/web/i18n/ko-KR/dataset-documents.ts
+++ b/web/i18n/ko-KR/dataset-documents.ts
@@ -388,6 +388,8 @@ const translation = {
addChunk: '청크 추가 (Add Chunk)',
characters_other: '문자',
regeneratingMessage: '시간이 걸릴 수 있으니 잠시만 기다려 주십시오...',
+ keywordDuplicate: '키워드가 이미 존재합니다.',
+ keywordEmpty: '키워드는 비워둘 수 없습니다.',
},
}
diff --git a/web/i18n/pl-PL/dataset-documents.ts b/web/i18n/pl-PL/dataset-documents.ts
index 37f373ac93..78e427ba95 100644
--- a/web/i18n/pl-PL/dataset-documents.ts
+++ b/web/i18n/pl-PL/dataset-documents.ts
@@ -390,6 +390,8 @@ const translation = {
newChildChunk: 'Nowy fragment podrzędny',
clearFilter: 'Wyczyść filtr',
childChunks_one: 'FRAGMENT POTOMNY',
+ keywordDuplicate: 'Słowo kluczowe już istnieje',
+ keywordEmpty: 'Słowo kluczowe nie może być puste',
},
}
diff --git a/web/i18n/pt-BR/dataset-documents.ts b/web/i18n/pt-BR/dataset-documents.ts
index 9a3d13bcab..b8c06c1769 100644
--- a/web/i18n/pt-BR/dataset-documents.ts
+++ b/web/i18n/pt-BR/dataset-documents.ts
@@ -389,6 +389,8 @@ const translation = {
newChildChunk: 'Novo pedaço filho',
characters_one: 'personagem',
parentChunk: 'Pedaço pai',
+ keywordEmpty: 'A palavra-chave não pode estar vazia',
+ keywordDuplicate: 'A palavra-chave já existe',
},
}
diff --git a/web/i18n/ro-RO/dataset-documents.ts b/web/i18n/ro-RO/dataset-documents.ts
index e42be87502..e0f3e8b476 100644
--- a/web/i18n/ro-RO/dataset-documents.ts
+++ b/web/i18n/ro-RO/dataset-documents.ts
@@ -389,6 +389,8 @@ const translation = {
regeneratingTitle: 'Regenerarea bucăților secundare',
addChildChunk: 'Adăugați o bucată copil',
searchResults_other: 'REZULTATELE',
+ keywordDuplicate: 'Cuvântul cheie există deja',
+ keywordEmpty: 'Cuvântul cheie nu poate fi gol',
},
}
diff --git a/web/i18n/ru-RU/dataset-documents.ts b/web/i18n/ru-RU/dataset-documents.ts
index 735266c087..6fadee3b26 100644
--- a/web/i18n/ru-RU/dataset-documents.ts
+++ b/web/i18n/ru-RU/dataset-documents.ts
@@ -389,6 +389,8 @@ const translation = {
characters_one: 'характер',
addChildChunk: 'Добавить дочерний чанк',
newChildChunk: 'Новый дочерний чанк',
+ keywordEmpty: 'Ключевое слово не может быть пустым',
+ keywordDuplicate: 'Ключевое слово уже существует',
},
}
diff --git a/web/i18n/sl-SI/dataset-documents.ts b/web/i18n/sl-SI/dataset-documents.ts
index 78d63c9e29..1a83335ad5 100644
--- a/web/i18n/sl-SI/dataset-documents.ts
+++ b/web/i18n/sl-SI/dataset-documents.ts
@@ -389,6 +389,8 @@ const translation = {
chunk: 'Kos',
addChunk: 'Dodajanje kosa',
childChunkAdded: 'Dodan je 1 kos otroka',
+ keywordDuplicate: 'Ključna beseda že obstaja',
+ keywordEmpty: 'Ključna beseda ne more biti prazna',
},
}
diff --git a/web/i18n/th-TH/dataset-documents.ts b/web/i18n/th-TH/dataset-documents.ts
index 91d04d6bc1..87b43f31e2 100644
--- a/web/i18n/th-TH/dataset-documents.ts
+++ b/web/i18n/th-TH/dataset-documents.ts
@@ -388,6 +388,8 @@ const translation = {
searchResults_other: 'ผลลัพธ์',
regenerationSuccessMessage: 'คุณสามารถปิดหน้าต่างนี้ได้',
childChunks_one: 'ก้อนเด็ก',
+ keywordDuplicate: 'คำสำคัญมีอยู่แล้ว',
+ keywordEmpty: 'คีย์เวิร์ดไม่สามารถว่างเปล่าได้',
},
}
diff --git a/web/i18n/tr-TR/dataset-documents.ts b/web/i18n/tr-TR/dataset-documents.ts
index f643375334..2e00975178 100644
--- a/web/i18n/tr-TR/dataset-documents.ts
+++ b/web/i18n/tr-TR/dataset-documents.ts
@@ -388,6 +388,8 @@ const translation = {
chunks_other: 'Parçalar',
editedAt: 'Şurada düzenlendi:',
addChildChunk: 'Alt Parça Ekle',
+ keywordDuplicate: 'Anahtar kelime zaten var',
+ keywordEmpty: 'Anahtar kelime boş olamaz',
},
}
diff --git a/web/i18n/uk-UA/dataset-documents.ts b/web/i18n/uk-UA/dataset-documents.ts
index da012cbb57..e8464e5661 100644
--- a/web/i18n/uk-UA/dataset-documents.ts
+++ b/web/i18n/uk-UA/dataset-documents.ts
@@ -389,6 +389,8 @@ const translation = {
regenerationSuccessMessage: 'Ви можете закрити це вікно.',
expandChunks: 'Розгортання фрагментів',
regenerationConfirmTitle: 'Хочете регенерувати дитячі шматки?',
+ keywordEmpty: 'Ключове слово не може бути порожнім',
+ keywordDuplicate: 'Ключове слово вже існує',
},
}
diff --git a/web/i18n/vi-VN/dataset-documents.ts b/web/i18n/vi-VN/dataset-documents.ts
index 6e13c1185f..1cc050b804 100644
--- a/web/i18n/vi-VN/dataset-documents.ts
+++ b/web/i18n/vi-VN/dataset-documents.ts
@@ -388,6 +388,8 @@ const translation = {
clearFilter: 'Bộ lọc rõ ràng',
chunk: 'Khúc',
edited: 'EDITED',
+ keywordDuplicate: 'Từ khóa đã tồn tại',
+ keywordEmpty: 'Từ khóa không được để trống',
},
}
diff --git a/web/i18n/zh-Hans/dataset-documents.ts b/web/i18n/zh-Hans/dataset-documents.ts
index 5ff1b50f85..2eb883690b 100644
--- a/web/i18n/zh-Hans/dataset-documents.ts
+++ b/web/i18n/zh-Hans/dataset-documents.ts
@@ -387,6 +387,8 @@ const translation = {
editedAt: '编辑于',
expandChunks: '展开分段',
collapseChunks: '折叠分段',
+ keywordEmpty: '关键词不能为空',
+ keywordDuplicate: '关键词已经存在',
},
}
diff --git a/web/i18n/zh-Hans/workflow.ts b/web/i18n/zh-Hans/workflow.ts
index b41fde747c..4a040ca46a 100644
--- a/web/i18n/zh-Hans/workflow.ts
+++ b/web/i18n/zh-Hans/workflow.ts
@@ -556,6 +556,7 @@ const translation = {
advancedDependencies: '高级依赖',
advancedDependenciesTip: '在这里添加一些预加载需要消耗较多时间或非默认内置的依赖包',
searchDependencies: '搜索依赖',
+ syncFunctionSignature: '同步函数签名至代码',
},
templateTransform: {
inputVars: '输入变量',
diff --git a/web/i18n/zh-Hant/dataset-documents.ts b/web/i18n/zh-Hant/dataset-documents.ts
index 60b1df80f3..a79f3993e0 100644
--- a/web/i18n/zh-Hant/dataset-documents.ts
+++ b/web/i18n/zh-Hant/dataset-documents.ts
@@ -388,6 +388,8 @@ const translation = {
searchResults_zero: '結果',
parentChunks_other: '父塊',
newChildChunk: '新兒童塊',
+ keywordEmpty: '關鍵字不能為空',
+ keywordDuplicate: '關鍵字已經存在',
},
}
diff --git a/web/i18n/zh-Hant/workflow.ts b/web/i18n/zh-Hant/workflow.ts
index 2ee345eccc..8262e60351 100644
--- a/web/i18n/zh-Hant/workflow.ts
+++ b/web/i18n/zh-Hant/workflow.ts
@@ -544,6 +544,7 @@ const translation = {
advancedDependencies: '高級依賴',
advancedDependenciesTip: '在這裡添加一些預加載需要消耗較多時間或非默認內置的依賴包',
searchDependencies: '搜索依賴',
+ syncFunctionSignature: '同步函數簽名至代碼',
},
templateTransform: {
inputVars: '輸入變量',
diff --git a/web/service/access-control.ts b/web/service/access-control.ts
index 865909d2f9..36999bf8f3 100644
--- a/web/service/access-control.ts
+++ b/web/service/access-control.ts
@@ -86,5 +86,8 @@ export const useGetUserCanAccessApp = ({ appId, isInstalledApp = true, enabled }
enabled: !!appId && enabled,
staleTime: 0,
gcTime: 0,
+ initialData: {
+ result: !enabled,
+ },
})
}
diff --git a/web/service/use-workflow.ts b/web/service/use-workflow.ts
index 697916b855..c9a0023c99 100644
--- a/web/service/use-workflow.ts
+++ b/web/service/use-workflow.ts
@@ -149,7 +149,7 @@ export const useResetConversationVar = (appId: string) => {
export const useResetToLastRunValue = (appId: string) => {
return useMutation({
mutationKey: [NAME_SPACE, 'reset to last run value', appId],
- mutationFn: async (varId: string) => {
+ mutationFn: async (varId: string): Promise<{ value: any }> => {
return put(`apps/${appId}/workflows/draft/variables/${varId}/reset`)
},
})
diff --git a/web/utils/completion-params.ts b/web/utils/completion-params.ts
new file mode 100644
index 0000000000..b46c3ab720
--- /dev/null
+++ b/web/utils/completion-params.ts
@@ -0,0 +1,88 @@
+import type { FormValue, ModelParameterRule } from '@/app/components/header/account-setting/model-provider-page/declarations'
+
+export const mergeValidCompletionParams = (
+ oldParams: FormValue | undefined,
+ rules: ModelParameterRule[],
+): { params: FormValue; removedDetails: Record } => {
+ if (!oldParams || Object.keys(oldParams).length === 0)
+ return { params: {}, removedDetails: {} }
+
+ const acceptedKeys = new Set(rules.map(r => r.name))
+ const ruleMap: Record = {}
+ rules.forEach((r) => {
+ ruleMap[r.name] = r
+ })
+
+ const nextParams: FormValue = {}
+ const removedDetails: Record = {}
+
+ Object.entries(oldParams).forEach(([key, value]) => {
+ if (!acceptedKeys.has(key)) {
+ removedDetails[key] = 'unsupported'
+ return
+ }
+
+ const rule = ruleMap[key]
+ if (!rule) {
+ removedDetails[key] = 'unsupported'
+ return
+ }
+
+ switch (rule.type) {
+ case 'int':
+ case 'float': {
+ if (typeof value !== 'number') {
+ removedDetails[key] = 'invalid type'
+ return
+ }
+ const min = rule.min ?? Number.NEGATIVE_INFINITY
+ const max = rule.max ?? Number.POSITIVE_INFINITY
+ if (value < min || value > max) {
+ removedDetails[key] = `out of range (${min}-${max})`
+ return
+ }
+ nextParams[key] = value
+ return
+ }
+ case 'boolean': {
+ if (typeof value !== 'boolean') {
+ removedDetails[key] = 'invalid type'
+ return
+ }
+ nextParams[key] = value
+ return
+ }
+ case 'string':
+ case 'text': {
+ if (typeof value !== 'string') {
+ removedDetails[key] = 'invalid type'
+ return
+ }
+ if (Array.isArray(rule.options) && rule.options.length) {
+ if (!(rule.options as string[]).includes(value)) {
+ removedDetails[key] = 'unsupported option'
+ return
+ }
+ }
+ nextParams[key] = value
+ return
+ }
+ default: {
+ removedDetails[key] = `unsupported rule type: ${(rule as any)?.type ?? 'unknown'}`
+ }
+ }
+ })
+
+ return { params: nextParams, removedDetails }
+}
+
+export const fetchAndMergeValidCompletionParams = async (
+ provider: string,
+ modelId: string,
+ oldParams: FormValue | undefined,
+): Promise<{ params: FormValue; removedDetails: Record }> => {
+ const { fetchModelParameterRules } = await import('@/service/common')
+ const url = `/workspaces/current/model-providers/${provider}/models/parameter-rules?model=${modelId}`
+ const { data: parameterRules } = await fetchModelParameterRules(url)
+ return mergeValidCompletionParams(oldParams, parameterRules ?? [])
+}