From bffbe5412096e8fb0d95c1655d52222e62ab6220 Mon Sep 17 00:00:00 2001 From: zyileven <40888939+zyileven@users.noreply.github.com> Date: Wed, 3 Sep 2025 14:48:30 +0800 Subject: [PATCH 01/15] =?UTF-8?q?fix:=20=20Solve=20the=20problem=20of=20op?= =?UTF-8?q?ening=20remarks=20appearing=20in=20the=20chat=20cont=E2=80=A6?= =?UTF-8?q?=20(#25067)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/chat-with-history/chat-wrapper.tsx | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx b/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx index e856e6a88a..cc5e46deeb 100644 --- a/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx +++ b/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx @@ -52,6 +52,10 @@ const ChatWrapper = () => { allInputsHidden, initUserVariables, } = useChatWithHistoryContext() + + // Semantic variable for better code readability + const isHistoryConversation = !!currentConversationId + const appConfig = useMemo(() => { const config = appParams || {} @@ -62,9 +66,9 @@ const ChatWrapper = () => { fileUploadConfig: (config as any).system_parameters, }, supportFeedback: true, - opening_statement: currentConversationId ? currentConversationItem?.introduction : (config as any).opening_statement, + opening_statement: isHistoryConversation ? currentConversationItem?.introduction : (config as any).opening_statement, } as ChatConfig - }, [appParams, currentConversationItem?.introduction, currentConversationId]) + }, [appParams, currentConversationItem?.introduction, isHistoryConversation]) const { chatList, setTargetMessageId, @@ -75,7 +79,7 @@ const ChatWrapper = () => { } = useChat( appConfig, { - inputs: (currentConversationId ? currentConversationInputs : newConversationInputs) as any, + inputs: (isHistoryConversation ? currentConversationInputs : newConversationInputs) as any, inputsForm: inputsForms, }, appPrevChatTree, @@ -83,7 +87,7 @@ const ChatWrapper = () => { clearChatList, setClearChatList, ) - const inputsFormValue = currentConversationId ? currentConversationInputs : newConversationInputsRef?.current + const inputsFormValue = isHistoryConversation ? currentConversationInputs : newConversationInputsRef?.current const inputDisabled = useMemo(() => { if (allInputsHidden) return false @@ -132,7 +136,7 @@ const ChatWrapper = () => { const data: any = { query: message, files, - inputs: formatBooleanInputs(inputsForms, currentConversationId ? currentConversationInputs : newConversationInputs), + inputs: formatBooleanInputs(inputsForms, isHistoryConversation ? currentConversationInputs : newConversationInputs), conversation_id: currentConversationId, parent_message_id: (isRegenerate ? parentAnswer?.id : getLastAnswer(chatList)?.id) || null, } @@ -142,11 +146,11 @@ const ChatWrapper = () => { data, { onGetSuggestedQuestions: responseItemId => fetchSuggestedQuestions(responseItemId, isInstalledApp, appId), - onConversationComplete: currentConversationId ? undefined : handleNewConversationCompleted, + onConversationComplete: isHistoryConversation ? undefined : handleNewConversationCompleted, isPublicAPI: !isInstalledApp, }, ) - }, [chatList, handleNewConversationCompleted, handleSend, currentConversationId, currentConversationInputs, newConversationInputs, isInstalledApp, appId]) + }, [chatList, handleNewConversationCompleted, handleSend, isHistoryConversation, currentConversationInputs, newConversationInputs, isInstalledApp, appId]) const doRegenerate = useCallback((chatItem: ChatItemInTree, editedQuestion?: { message: string, files?: FileEntity[] }) => { const question = editedQuestion ? chatItem : chatList.find(item => item.id === chatItem.parentMessageId)! @@ -159,31 +163,30 @@ const ChatWrapper = () => { }, [chatList, doSend]) const messageList = useMemo(() => { - if (currentConversationId) - return chatList + // Always filter out opening statement from message list as it's handled separately in welcome component return chatList.filter(item => !item.isOpeningStatement) - }, [chatList, currentConversationId]) + }, [chatList]) - const [collapsed, setCollapsed] = useState(!!currentConversationId) + const [collapsed, setCollapsed] = useState(isHistoryConversation) const chatNode = useMemo(() => { if (allInputsHidden || !inputsForms.length) return null if (isMobile) { - if (!currentConversationId) + if (!isHistoryConversation) return return null } else { return } - }, [inputsForms.length, isMobile, currentConversationId, collapsed, allInputsHidden]) + }, [inputsForms.length, isMobile, isHistoryConversation, collapsed, allInputsHidden]) const welcome = useMemo(() => { const welcomeMessage = chatList.find(item => item.isOpeningStatement) if (respondingState) return null - if (currentConversationId) + if (isHistoryConversation) return null if (!welcomeMessage) return null @@ -224,7 +227,7 @@ const ChatWrapper = () => { ) - }, [appData?.site.icon, appData?.site.icon_background, appData?.site.icon_type, appData?.site.icon_url, chatList, collapsed, currentConversationId, inputsForms.length, respondingState, allInputsHidden]) + }, [appData?.site.icon, appData?.site.icon_background, appData?.site.icon_type, appData?.site.icon_url, chatList, collapsed, isHistoryConversation, inputsForms.length, respondingState, allInputsHidden]) const answerIcon = (appData?.site && appData.site.use_icon_as_answer_icon) ? { chatFooterClassName='pb-4' chatFooterInnerClassName={`mx-auto w-full max-w-[768px] ${isMobile ? 'px-2' : 'px-4'}`} onSend={doSend} - inputs={currentConversationId ? currentConversationInputs as any : newConversationInputs} + inputs={isHistoryConversation ? currentConversationInputs as any : newConversationInputs} inputsForm={inputsForms} onRegenerate={doRegenerate} onStopResponding={handleStop} From 0e8a37dca879d942324454e706ca92dc3c7c0499 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 3 Sep 2025 14:48:53 +0800 Subject: [PATCH 02/15] chore: translate i18n files (#25061) Co-authored-by: zxhlyh <16177003+zxhlyh@users.noreply.github.com> --- web/i18n/de-DE/common.ts | 1 + web/i18n/fa-IR/common.ts | 1 + web/i18n/hi-IN/common.ts | 1 + web/i18n/ro-RO/common.ts | 1 + web/i18n/th-TH/common.ts | 1 + 5 files changed, 5 insertions(+) diff --git a/web/i18n/de-DE/common.ts b/web/i18n/de-DE/common.ts index 70f3d97037..dec18fd4f2 100644 --- a/web/i18n/de-DE/common.ts +++ b/web/i18n/de-DE/common.ts @@ -490,6 +490,7 @@ const translation = { providerManagedTip: 'Die aktuelle Konfiguration wird vom Anbieter gehostet.', configLoadBalancing: 'Konfiguration Lastenverteilung', specifyModelCredentialTip: 'Verwenden Sie ein konfiguriertes Modellzugang.', + manageCredentials: 'Anmeldeinformationen verwalten', }, }, dataSource: { diff --git a/web/i18n/fa-IR/common.ts b/web/i18n/fa-IR/common.ts index 84bda8dfa5..d78dd45662 100644 --- a/web/i18n/fa-IR/common.ts +++ b/web/i18n/fa-IR/common.ts @@ -494,6 +494,7 @@ const translation = { specifyModelCredentialTip: 'از اعتبارنامه مدل پیکربندی شده استفاده کنید.', providerManagedTip: 'تنظیمات فعلی توسط ارائه‌دهنده میزبانی می‌شود.', modelCredentials: 'مدل اعتبارنامه', + manageCredentials: 'مدیریت اعتبارنامه ها', }, }, dataSource: { diff --git a/web/i18n/hi-IN/common.ts b/web/i18n/hi-IN/common.ts index a2de883cd9..ade633dec5 100644 --- a/web/i18n/hi-IN/common.ts +++ b/web/i18n/hi-IN/common.ts @@ -510,6 +510,7 @@ const translation = { specifyModelCredential: 'मॉडल की क्रेडेंशियल निर्दिष्ट करें', specifyModelCredentialTip: 'कॉन्फ़िगर की गई मॉडल क्रेडेंशियल का उपयोग करें।', providerManagedTip: 'वर्तमान कॉन्फ़िगरेशन प्रदाता द्वारा होस्ट किया गया है।', + selectModelCredential: 'एक मॉडल क्रेडेंशियल चुनें', }, }, dataSource: { diff --git a/web/i18n/ro-RO/common.ts b/web/i18n/ro-RO/common.ts index 5fa8a9e2b2..eea41d1c0e 100644 --- a/web/i18n/ro-RO/common.ts +++ b/web/i18n/ro-RO/common.ts @@ -490,6 +490,7 @@ const translation = { providerManagedTip: 'Configurarea curentă este găzduită de furnizor.', modelCredentials: 'Credențiale model', specifyModelCredentialTip: 'Utilizați un acreditiv de model configurat.', + addNewModelCredential: 'Adăugați acreditive noi pentru model', }, }, dataSource: { diff --git a/web/i18n/th-TH/common.ts b/web/i18n/th-TH/common.ts index db30f103b3..b78ad47f22 100644 --- a/web/i18n/th-TH/common.ts +++ b/web/i18n/th-TH/common.ts @@ -489,6 +489,7 @@ const translation = { authorizationError: 'ข้อผิดพลาดในการอนุญาต', specifyModelCredentialTip: 'ใช้ข้อมูลรับรองโมเดลที่กำหนดไว้', providerManagedTip: 'การกำหนดค่าปัจจุบันถูกโฮสต์โดยผู้ให้บริการ.', + customModelCredentialsDeleteTip: 'ข้อมูลรับรองกำลังถูกใช้งานและไม่สามารถลบได้', }, }, dataSource: { From 462e764a3c0e3aedf1ad3d9f0f384eed1409786e Mon Sep 17 00:00:00 2001 From: Asuka Minato Date: Wed, 3 Sep 2025 15:54:38 +0900 Subject: [PATCH 03/15] typevar example (#25064) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- api/core/helper/position_helper.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/api/core/helper/position_helper.py b/api/core/helper/position_helper.py index 8def6fe4ed..314f052832 100644 --- a/api/core/helper/position_helper.py +++ b/api/core/helper/position_helper.py @@ -1,7 +1,7 @@ import os from collections import OrderedDict from collections.abc import Callable -from typing import Any +from typing import TypeVar from configs import dify_config from core.tools.utils.yaml_utils import load_yaml_file @@ -72,11 +72,14 @@ def pin_position_map(original_position_map: dict[str, int], pin_list: list[str]) return position_map +T = TypeVar("T") + + def is_filtered( include_set: set[str], exclude_set: set[str], - data: Any, - name_func: Callable[[Any], str], + data: T, + name_func: Callable[[T], str], ) -> bool: """ Check if the object should be filtered out. @@ -103,9 +106,9 @@ def is_filtered( def sort_by_position_map( position_map: dict[str, int], - data: list[Any], - name_func: Callable[[Any], str], -) -> list[Any]: + data: list[T], + name_func: Callable[[T], str], +): """ Sort the objects by the position map. If the name of the object is not in the position map, it will be put at the end. @@ -122,9 +125,9 @@ def sort_by_position_map( def sort_to_dict_by_position_map( position_map: dict[str, int], - data: list[Any], - name_func: Callable[[Any], str], -) -> OrderedDict[str, Any]: + data: list[T], + name_func: Callable[[T], str], +): """ Sort the objects into a ordered dict by the position map. If the name of the object is not in the position map, it will be put at the end. @@ -134,4 +137,4 @@ def sort_to_dict_by_position_map( :return: an OrderedDict with the sorted pairs of name and object """ sorted_items = sort_by_position_map(position_map, data, name_func) - return OrderedDict([(name_func(item), item) for item in sorted_items]) + return OrderedDict((name_func(item), item) for item in sorted_items) From dabf266048333789a2ff1408f94c3fcd636572ed Mon Sep 17 00:00:00 2001 From: dswl23 <127465898+dswl23@users.noreply.github.com> Date: Wed, 3 Sep 2025 15:22:42 +0800 Subject: [PATCH 04/15] Fix: handle 204 No Content response in MCP client (#25040) --- api/core/mcp/client/streamable_client.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/api/core/mcp/client/streamable_client.py b/api/core/mcp/client/streamable_client.py index 14e346c2f3..a2b003e717 100644 --- a/api/core/mcp/client/streamable_client.py +++ b/api/core/mcp/client/streamable_client.py @@ -246,6 +246,10 @@ class StreamableHTTPTransport: logger.debug("Received 202 Accepted") return + if response.status_code == 204: + logger.debug("Received 204 No Content") + return + if response.status_code == 404: if isinstance(message.root, JSONRPCRequest): self._send_session_terminated_error( From 8eae7a95be91df1d3b017429a4abdaee4ccf9b63 Mon Sep 17 00:00:00 2001 From: NeatGuyCoding <15627489+NeatGuyCoding@users.noreply.github.com> Date: Wed, 3 Sep 2025 15:23:04 +0800 Subject: [PATCH 05/15] Hotfix translation error (#25035) --- web/i18n/id-ID/app-annotation.ts | 20 +++++++-------- web/i18n/id-ID/app-api.ts | 26 +++++++++---------- web/i18n/id-ID/app-debug.ts | 8 +++--- web/i18n/id-ID/app-log.ts | 16 ++++++------ web/i18n/id-ID/app-overview.ts | 4 +-- web/i18n/id-ID/app.ts | 16 ++++++------ web/i18n/id-ID/common.ts | 36 +++++++++++++-------------- web/i18n/id-ID/custom.ts | 18 +++++++------- web/i18n/id-ID/dataset-creation.ts | 20 +++++++-------- web/i18n/id-ID/dataset-hit-testing.ts | 4 +-- web/i18n/id-ID/dataset-settings.ts | 2 +- web/i18n/id-ID/dataset.ts | 4 +-- web/i18n/id-ID/education.ts | 2 +- web/i18n/id-ID/explore.ts | 8 +++--- web/i18n/id-ID/login.ts | 26 +++++++++---------- web/i18n/id-ID/oauth.ts | 10 ++++---- web/i18n/id-ID/plugin.ts | 10 ++++---- web/i18n/id-ID/time.ts | 16 ++++++------ web/i18n/id-ID/workflow.ts | 26 +++++++++---------- web/i18n/tr-TR/common.ts | 2 +- web/i18n/uk-UA/common.ts | 2 +- 21 files changed, 138 insertions(+), 138 deletions(-) diff --git a/web/i18n/id-ID/app-annotation.ts b/web/i18n/id-ID/app-annotation.ts index 9ac49fc977..bfc13c9d19 100644 --- a/web/i18n/id-ID/app-annotation.ts +++ b/web/i18n/id-ID/app-annotation.ts @@ -5,10 +5,10 @@ const translation = { }, table: { header: { - answer: 'menjawab', + answer: 'Jawaban', question: 'pertanyaan', createdAt: 'dibuat di', - hits: 'Hits', + hits: 'Kecocokan', addAnnotation: 'Tambahkan Anotasi', bulkImport: 'Impor Massal', clearAllConfirm: 'Menghapus semua anotasi?', @@ -29,7 +29,7 @@ const translation = { answerName: 'Bot Pendongeng', }, addModal: { - answerName: 'Menjawab', + answerName: 'Jawaban', title: 'Tambahkan Anotasi Balasan', queryName: 'Pertanyaan', createNext: 'Tambahkan respons beranotasi lainnya', @@ -44,10 +44,10 @@ const translation = { run: 'Jalankan Batch', cancel: 'Membatalkan', title: 'Impor Massal', - browse: 'ramban', + browse: 'Telusuri', template: 'Unduh templat di sini', tip: 'File CSV harus sesuai dengan struktur berikut:', - answer: 'menjawab', + answer: 'Jawaban', contentTitle: 'konten potongan', processing: 'Dalam pemrosesan batch', completed: 'Impor selesai', @@ -69,15 +69,15 @@ const translation = { answerRequired: 'Jawaban diperlukan', }, viewModal: { - hit: 'Pukul', - hitHistory: 'Riwayat Hit', - noHitHistory: 'Tidak ada riwayat hit', + hit: 'Kecocokan', + hitHistory: 'Riwayat Kecocokan', + noHitHistory: 'Tidak ada riwayat kecocokan', annotatedResponse: 'Balas Anotasi', - hits: 'Hits', + hits: 'Kecocokan', }, hitHistoryTable: { response: 'Jawaban', - match: 'Korek api', + match: 'Kecocokan', query: 'Kueri', source: 'Sumber', time: 'Waktu', diff --git a/web/i18n/id-ID/app-api.ts b/web/i18n/id-ID/app-api.ts index fe528eebd4..627422a6b0 100644 --- a/web/i18n/id-ID/app-api.ts +++ b/web/i18n/id-ID/app-api.ts @@ -19,8 +19,8 @@ const translation = { completionMode: { createCompletionApi: 'Membuat Pesan Penyelesaian', messageIDTip: 'ID Pesan', - messageFeedbackApi: 'Umpan balik pesan (seperti)', - ratingTip: 'suka atau tidak suka, null adalah undo', + messageFeedbackApi: 'Umpan balik pesan (mis. spam, tidak relevan, pujian)', + ratingTip: '(mis. suka/tidak suka), null berarti membatalkan penilaian', parametersApi: 'Dapatkan informasi parameter aplikasi', parametersApiTip: 'Ambil parameter Input yang dikonfigurasi, termasuk nama variabel, nama bidang, jenis, dan nilai default. Biasanya digunakan untuk menampilkan bidang ini dalam formulir atau mengisi nilai default setelah klien dimuat.', info: 'Untuk pembuatan teks berkualitas tinggi, seperti artikel, ringkasan, dan terjemahan, gunakan API pesan penyelesaian dengan input pengguna. Pembuatan teks bergantung pada parameter model dan templat prompt yang ditetapkan di Dify Prompt Engineering.', @@ -48,7 +48,7 @@ const translation = { conversationsListLimitTip: 'Berapa banyak obrolan yang dikembalikan dalam satu permintaan', chatMsgHistoryLimit: 'Berapa banyak obrolan yang dikembalikan dalam satu permintaan', conversationsListFirstIdTip: 'ID rekaman terakhir di halaman saat ini, default tidak ada.', - messageFeedbackApi: 'Umpan balik pengguna terminal pesan, seperti', + messageFeedbackApi: 'Umpan balik pengguna terminal pesan (mis. spam, tidak relevan, pujian)', parametersApi: 'Dapatkan informasi parameter aplikasi', streaming: 'streaming kembali. Implementasi pengembalian streaming berdasarkan SSE (Server-Sent Events).', inputsTips: '(Opsional) Berikan bidang input pengguna sebagai pasangan kunci-nilai, sesuai dengan variabel di Prompt Eng. Kunci adalah nama variabel, Nilai adalah nilai parameter. Jika jenis bidang adalah Pilih, Nilai yang dikirimkan harus menjadi salah satu pilihan prasetel.', @@ -58,7 +58,7 @@ const translation = { createChatApiTip: 'Buat pesan percakapan baru atau lanjutkan dialog yang ada.', chatMsgHistoryApiTip: 'Halaman pertama mengembalikan bilah \'batas\' terbaru, yang dalam urutan terbalik.', conversationsListApi: 'Dapatkan daftar percakapan', - ratingTip: 'suka atau tidak suka, null adalah undo', + ratingTip: '(mis. suka/tidak suka), null berarti membatalkan penilaian', conversationRenamingApi: 'Penggantian nama percakapan', }, develop: { @@ -67,19 +67,19 @@ const translation = { pathParams: 'Parameter Jalur', requestBody: 'Isi Permintaan', }, - apiServer: 'API Server', + apiServer: 'Server API', copied: 'Disalin', - copy: 'Menyalin', - ok: 'Dalam Layanan', - regenerate: 'Regenerasi', - status: 'Keadaan', + copy: 'Salin', + ok: 'OK', + regenerate: 'Hasilkan Ulang', + status: 'Status', never: 'Tidak pernah', - playing: 'Bermain', - play: 'Bermain', - disabled: 'Cacat', + playing: 'Sedang Memutar', + play: 'Putar', + disabled: 'Dinonaktifkan', apiKey: 'Kunci API', pause: 'Jeda', - loading: 'Loading', + loading: 'Memuat...', } export default translation diff --git a/web/i18n/id-ID/app-debug.ts b/web/i18n/id-ID/app-debug.ts index 5d8575c43b..1d2056117b 100644 --- a/web/i18n/id-ID/app-debug.ts +++ b/web/i18n/id-ID/app-debug.ts @@ -324,7 +324,7 @@ const translation = { }, variableTable: { action: 'Tindakan', - typeString: 'Tali', + typeString: 'String', optional: 'Fakultatif', typeSelect: 'Pilih', type: 'Jenis Masukan', @@ -346,7 +346,7 @@ const translation = { name: 'Audio', }, document: { - name: 'Surat', + name: 'Dokumen', }, video: { name: 'Video', @@ -421,7 +421,7 @@ const translation = { language: 'Bahasa', title: 'Pengaturan Suara', autoPlay: 'Putar Otomatis', - autoPlayDisabled: 'Off', + autoPlayDisabled: 'Dinonaktifkan', resolutionTooltip: 'Bahasa pendukung suara text-to-speech。', }, settings: 'Pengaturan', @@ -448,7 +448,7 @@ const translation = { }, inputs: { queryPlaceholder: 'Silakan masukkan teks permintaan.', - run: 'LARI', + run: 'Jalankan', completionVarTip: 'Isi nilai variabel, yang akan secara otomatis diganti dengan kata-kata prompt setiap kali pertanyaan diajukan.', noVar: 'Isi nilai variabel, yang akan secara otomatis diganti dalam kata prompt setiap kali sesi baru dimulai.', noPrompt: 'Coba tulis beberapa prompt dalam input pra-prompt', diff --git a/web/i18n/id-ID/app-log.ts b/web/i18n/id-ID/app-log.ts index a33190f37e..1ccf8dec1e 100644 --- a/web/i18n/id-ID/app-log.ts +++ b/web/i18n/id-ID/app-log.ts @@ -5,8 +5,8 @@ const translation = { version: 'VERSI', time: 'Waktu yang dibuat', messageCount: 'Jumlah Pesan', - summary: 'Titel', - adminRate: 'Tingkat Op.', + summary: 'Ringkasan', + adminRate: 'Tingkat Admin', user: 'Pengguna Akhir atau Akun', startTime: 'WAKTU MULAI', updatedTime: 'Waktu yang diperbarui', @@ -18,8 +18,8 @@ const translation = { runtime: 'WAKTU BERJALAN', }, pagination: { - previous: 'Prev', - next: 'Depan', + previous: 'Sebelumnya', + next: 'Selanjutnya', }, empty: { element: { @@ -30,12 +30,12 @@ const translation = { }, }, detail: { - timeConsuming: '', + timeConsuming: 'Memakan waktu', operation: { dislike: 'tidak suka', like: 'suka', - addAnnotation: 'Tambahkan Peningkatan', - editAnnotation: 'Edit Peningkatan', + addAnnotation: 'Tambahkan Anotasi', + editAnnotation: 'Edit Anotasi', annotationPlaceholder: 'Masukkan jawaban yang diharapkan yang Anda inginkan untuk dibalas AI, yang dapat digunakan untuk penyempurnaan model dan peningkatan berkelanjutan kualitas pembuatan teks di masa mendatang.', }, time: 'Waktu', @@ -67,7 +67,7 @@ const translation = { }, ascending: 'Naik', descending: 'Turun', - sortBy: 'Kota hitam:', + sortBy: 'Urutkan berdasarkan', }, runDetail: { fileListDetail: 'Detail', diff --git a/web/i18n/id-ID/app-overview.ts b/web/i18n/id-ID/app-overview.ts index ce644e2c16..474e85bfd5 100644 --- a/web/i18n/id-ID/app-overview.ts +++ b/web/i18n/id-ID/app-overview.ts @@ -119,8 +119,8 @@ const translation = { explanation: 'Mudah diintegrasikan ke dalam aplikasi Anda', }, status: { - disable: 'Cacat', - running: 'Dalam Layanan', + disable: 'Nonaktif', + running: 'Berjalan', }, title: 'Ikhtisar', }, diff --git a/web/i18n/id-ID/app.ts b/web/i18n/id-ID/app.ts index 0788b96e23..05ab9fbe49 100644 --- a/web/i18n/id-ID/app.ts +++ b/web/i18n/id-ID/app.ts @@ -23,7 +23,7 @@ const translation = { appCreated: 'Aplikasi dibuat', appNamePlaceholder: 'Beri nama aplikasi Anda', appCreateDSLErrorPart3: 'Versi DSL aplikasi saat ini:', - Cancel: 'Membatalkan', + Cancel: 'Batal', previewDemo: 'Pratinjau demo', appCreateDSLWarning: 'Perhatian: Perbedaan versi DSL dapat memengaruhi fitur tertentu', appCreateDSLErrorPart1: 'Perbedaan yang signifikan dalam versi DSL telah terdeteksi. Memaksa impor dapat menyebabkan aplikasi tidak berfungsi.', @@ -46,7 +46,7 @@ const translation = { showTemplates: 'Saya ingin memilih dari templat', caution: 'Hati', chatbotShortDescription: 'Chatbot berbasis LLM dengan pengaturan sederhana', - Confirm: 'Mengkonfirmasi', + Confirm: 'Konfirmasi', agentAssistant: 'Asisten Agen Baru', appCreateFailed: 'Gagal membuat aplikasi', appCreateDSLErrorTitle: 'Ketidakcocokan Versi', @@ -58,7 +58,7 @@ const translation = { appTypeRequired: 'Silakan pilih jenis aplikasi', advancedShortDescription: 'Alur kerja disempurnakan untuk obrolan multi-giliran', completeAppIntro: 'Saya ingin membuat aplikasi yang menghasilkan teks berkualitas tinggi berdasarkan petunjuk, seperti menghasilkan artikel, ringkasan, terjemahan, dan banyak lagi.', - Create: 'Menciptakan', + Create: 'Buat', advancedUserDescription: 'Alur kerja dengan fitur memori tambahan dan antarmuka chatbot.', dropDSLToCreateApp: 'Jatuhkan file DSL di sini untuk membuat aplikasi', completeApp: 'Pembuat Teks', @@ -83,10 +83,10 @@ const translation = { searchAllTemplate: 'Cari semua templat...', }, iconPicker: { - cancel: 'Membatalkan', + cancel: 'Batal', emoji: 'Emoji', image: 'Citra', - ok: 'OKE', + ok: 'OK', }, answerIcon: { title: 'Gunakan ikon aplikasi web untuk mengganti 🤖', @@ -129,7 +129,7 @@ const translation = { }, weave: { description: 'Weave adalah platform sumber terbuka untuk mengevaluasi, menguji, dan memantau aplikasi LLM.', - title: 'Anyam', + title: 'Weave', }, aliyun: { title: 'Monitor Awan', @@ -148,8 +148,8 @@ const translation = { collapse: 'Roboh', tracing: 'Menelusuri', title: 'Melacak performa aplikasi', - disabled: 'Cacat', - enabled: 'Dalam Layanan', + disabled: 'Nonaktif', + enabled: 'Aktif', config: 'Konfigurasi', description: 'Mengonfigurasi penyedia LLMOps Pihak Ketiga dan melacak performa aplikasi.', inUse: 'Sedang digunakan', diff --git a/web/i18n/id-ID/common.ts b/web/i18n/id-ID/common.ts index 6cfb9577c4..5dafec233e 100644 --- a/web/i18n/id-ID/common.ts +++ b/web/i18n/id-ID/common.ts @@ -1,9 +1,9 @@ const translation = { theme: { theme: 'Tema', - light: 'ringan', - auto: 'sistem', - dark: 'gelap', + light: 'Terang', + auto: 'Otomatis', + dark: 'Gelap', }, api: { success: 'Keberhasilan', @@ -16,8 +16,8 @@ const translation = { setup: 'Setup', download: 'Mengunduh', getForFree: 'Dapatkan gratis', - reload: 'Reload', - lineBreak: 'Istirahat baris', + reload: 'Muat Ulang', + lineBreak: 'Baris Baru', learnMore: 'Pelajari lebih lanjut', saveAndRegenerate: 'Simpan & Buat Ulang Potongan Anak', zoomOut: 'Perkecil', @@ -26,7 +26,7 @@ const translation = { selectAll: 'Pilih Semua', in: 'di', skip: 'Lewat', - remove: 'Buka', + remove: 'Hapus', rename: 'Ubah nama', close: 'Tutup', ok: 'OKE', @@ -35,8 +35,8 @@ const translation = { log: 'Batang', delete: 'Menghapus', viewDetails: 'Lihat Detail', - view: 'Melihat', - clear: 'Jelas', + view: 'Lihat', + clear: 'Hapus', deleteApp: 'Hapus Aplikasi', downloadSuccess: 'Unduh Selesai.', change: 'Ubah', @@ -45,7 +45,7 @@ const translation = { copied: 'Disalin', deSelectAll: 'Batalkan pilihan Semua', saveAndEnable: 'Simpan & Aktifkan', - refresh: 'Restart', + refresh: 'Segarkan', downloadFailed: 'Unduhan gagal. Silakan coba lagi nanti.', edit: 'Mengedit', send: 'Kirim', @@ -56,7 +56,7 @@ const translation = { add: 'Tambah', copy: 'Menyalin', audioSourceUnavailable: 'AudioSource tidak tersedia', - submit: 'Tunduk', + submit: 'Kirim', duplicate: 'Duplikat', save: 'Simpan', added: 'Ditambahkan', @@ -100,7 +100,7 @@ const translation = { }, }, unit: { - char: 'Tank', + char: 'karakter', }, actionMsg: { noModification: 'Tidak ada modifikasi saat ini.', @@ -148,7 +148,7 @@ const translation = { account: 'Rekening', newApp: 'Aplikasi Baru', explore: 'Menjelajahi', - apps: 'Belajar', + apps: 'Aplikasi', status: 'beta', tools: 'Perkakas', exploreMarketplace: 'Jelajahi Marketplace', @@ -165,7 +165,7 @@ const translation = { settings: 'Pengaturan', support: 'Dukung', github: 'GitHub', - about: 'Sekitar', + about: 'Tentang', workspace: 'Workspace', createWorkspace: 'Membuat Ruang Kerja', }, @@ -503,13 +503,13 @@ const translation = { }, integratedAlert: 'Notion terintegrasi melalui kredensial internal, tidak perlu mengotorisasi ulang.', disconnected: 'Terputus', - remove: 'Buka', + remove: 'Hapus', addWorkspace: 'Menambahkan ruang kerja', description: 'Menggunakan Notion sebagai sumber data untuk Pengetahuan.', connected: 'Terhubung', pagesAuthorized: 'Halaman yang disahkan', changeAuthorizedPages: 'Mengubah halaman resmi', - title: 'Gagasan', + title: 'Notion', sync: 'Sync', connectedWorkspace: 'Ruang kerja yang terhubung', }, @@ -597,7 +597,7 @@ const translation = { 'claude-2': 'Claude-2', 'gpt-3.5-turbo': 'GPT-3.5-Turbo', 'gpt-4': 'GPT-4', - 'whisper-1': 'Bisikan-1', + 'whisper-1': 'Whisper-1', 'text-davinci-003': 'Teks-Davinci-003', 'gpt-4-32k': 'GPT-4-32K', 'gpt-3.5-turbo-16k': 'GPT-3.5-Turbo-16K', @@ -615,7 +615,7 @@ const translation = { }, resend: 'Kirim Ulang', conversationName: 'Nama percakapan', - thinking: 'Pikiran...', + thinking: 'Sedang berpikir...', conversationNameCanNotEmpty: 'Nama percakapan diperlukan', thought: 'Pikiran', renameConversation: 'Ganti Nama Percakapan', @@ -712,7 +712,7 @@ const translation = { deleteDescription: 'Apakah Anda yakin ingin menghapus gambar profil Anda? Akun Anda akan menggunakan avatar awal default.', }, imageInput: { - browse: 'ramban', + browse: 'Telusuri', supportedFormats: 'Mendukung PNG, JPG, JPEG, WEBP dan GIF', dropImageHere: 'Letakkan gambar Anda di sini, atau', }, diff --git a/web/i18n/id-ID/custom.ts b/web/i18n/id-ID/custom.ts index 6b45241f16..c4a26800d2 100644 --- a/web/i18n/id-ID/custom.ts +++ b/web/i18n/id-ID/custom.ts @@ -7,25 +7,25 @@ const translation = { }, webapp: { changeLogoTip: 'Format SVG atau PNG dengan ukuran minimum 40x40px', - removeBrand: 'Hapus Didukung oleh Dify', - changeLogo: 'Perubahan Didukung oleh Citra Merek', - title: 'Sesuaikan merek aplikasi web', + removeBrand: 'Hapus Branding Dify', + changeLogo: 'Ubah Logo Merek', + title: 'Kustomisasi Branding Aplikasi Web', }, app: { - title: 'Menyesuaikan merek header aplikasi', + title: 'Kustomisasi Branding Header Aplikasi', changeLogoTip: 'Format SVG atau PNG dengan ukuran minimal 80x80px', }, customize: { - suffix: 'untuk meningkatkan ke edisi Enterprise.', - prefix: 'Untuk menyesuaikan logo merek di dalam aplikasi, silakan', - contactUs: 'Hubungi', + suffix: 'untuk upgrade ke edisi Enterprise.', + prefix: 'Untuk kustomisasi logo merek di dalam aplikasi, silakan', + contactUs: 'Hubungi Kami', }, custom: 'Kustomisasi', - uploading: 'Meng', + uploading: 'Mengunggah...', upload: 'Unggah', change: 'Ubah', restore: 'Pulihkan Default', - apply: 'Berlaku', + apply: 'Terapkan', uploadedFail: 'Unggahan gambar gagal, silakan unggah ulang.', } diff --git a/web/i18n/id-ID/dataset-creation.ts b/web/i18n/id-ID/dataset-creation.ts index 9c22751a25..2712f9af0f 100644 --- a/web/i18n/id-ID/dataset-creation.ts +++ b/web/i18n/id-ID/dataset-creation.ts @@ -56,17 +56,17 @@ const translation = { tip: 'Pengetahuan kosong tidak akan berisi dokumen, dan Anda dapat mengunggah dokumen kapan saja.', }, website: { - configure: 'Mengkonfigurasi', + configure: 'Konfigurasikan', fireCrawlNotConfigured: 'Firecrawl tidak dikonfigurasi', chooseProvider: 'Pilih penyedia', - configureFirecrawl: 'Mengonfigurasi Firecrawl', + configureFirecrawl: 'Konfigurasikan Firecrawl', watercrawlDoc: 'Dokumen Watercrawl', options: 'Pilihan', firecrawlTitle: 'Mengekstrak konten web dengan 🔥Firecrawl', jinaReaderNotConfigured: 'Jina Reader tidak dikonfigurasi', preview: 'Pratayang', resetAll: 'Atur Ulang Semua', - run: 'Lari', + run: 'Jalankan', limit: 'Batas', useSitemap: 'Menggunakan peta situs', jinaReaderDoc: 'Pelajari lebih lanjut tentang Jina Reader', @@ -87,19 +87,19 @@ const translation = { maxDepth: 'Kedalaman maks', jinaReaderDocLink: 'https://jina.ai/reader', selectAll: 'Pilih Semua', - maxDepthTooltip: 'Kedalaman maksimum untuk di-crawl relatif terhadap URL yang dimasukkan. Kedalaman 0 hanya mengikis halaman url yang dimasukkan, kedalaman 1 mengikis url dan semuanya setelah dimasukkanURL satu /, dan seterusnya.', + maxDepthTooltip: 'Kedalaman maksimum untuk di-crawl relatif terhadap URL yang dimasukkan. Kedalaman 0 hanya mengikis halaman url yang dimasukkan, kedalaman 1 mengikis url dan semuanya setelah dimasukkan URL satu /, dan seterusnya.', waterCrawlNotConfiguredDescription: 'Konfigurasikan Watercrawl dengan kunci API untuk menggunakannya.', firecrawlDoc: 'Dokumen Firecrawl', - configureWatercrawl: 'Mengonfigurasi Watercrawl', + configureWatercrawl: 'Konfigurasikan Watercrawl', }, pagePreview: 'Pratinjau Halaman', - notionSyncTitle: 'Gagasan tidak terhubung', + notionSyncTitle: 'Notion tidak terhubung', filePreview: 'Pratinjau File', cancel: 'Membatalkan', emptyDatasetCreation: 'Saya ingin membuat Pengetahuan kosong', - button: 'Depan', + button: 'Berikutnya', notionSyncTip: 'Untuk menyinkronkan dengan Notion, koneksi ke Notion harus dibuat terlebih dahulu.', - connect: 'Buka terhubung', + connect: 'Hubungkan', }, stepTwo: { paragraph: 'Paragraf', @@ -162,7 +162,7 @@ const translation = { previewChunkTip: 'Klik tombol \'Pratinjau Potongan\' di sebelah kiri untuk memuat pratinjau', sideTipP4: 'Potongan dan pembersihan yang tepat meningkatkan kinerja model, memberikan hasil yang lebih akurat dan berharga.', previewTitleButton: 'Pratayang', - switch: 'Sakelar', + switch: 'Beralih', datasetSettingLink: 'Pengaturan pengetahuan.', rules: 'Aturan Pra-pemrosesan Teks', sideTipP2: 'Segmentasi membagi teks panjang menjadi paragraf sehingga model dapat memahami dengan lebih baik. Ini meningkatkan kualitas dan relevansi hasil model.', @@ -193,7 +193,7 @@ const translation = { resume: 'Melanjutkan pemrosesan', stop: 'Hentikan pemrosesan', creationContent: 'Kami secara otomatis menamai Pengetahuan, Anda dapat memodifikasinya kapan saja.', - modelButtonConfirm: 'Mengkonfirmasi', + modelButtonConfirm: 'Konfirmasi', sideTipContent: 'Setelah dokumen selesai diindeks, Pengetahuan dapat diintegrasikan ke dalam aplikasi sebagai konteks, Anda dapat menemukan pengaturan konteks di halaman orkestrasi perintah. Anda juga dapat membuatnya sebagai plugin pengindeksan ChatGPT independen untuk dirilis.', modelButtonCancel: 'Membatalkan', label: 'Nama pengetahuan', diff --git a/web/i18n/id-ID/dataset-hit-testing.ts b/web/i18n/id-ID/dataset-hit-testing.ts index c66f650c52..d2a66eef08 100644 --- a/web/i18n/id-ID/dataset-hit-testing.ts +++ b/web/i18n/id-ID/dataset-hit-testing.ts @@ -11,7 +11,7 @@ const translation = { countWarning: 'Hingga 200 karakter.', placeholder: 'Silakan masukkan teks, disarankan untuk memasukkan kalimat deklaratif singkat.', indexWarning: 'Pengetahuan berkualitas tinggi saja.', - testing: 'Ujian', + testing: 'Pengujian', }, hit: { emptyTip: 'Hasil Pengujian Pengambilan akan ditampilkan di sini', @@ -22,7 +22,7 @@ const translation = { open: 'Buka', settingTitle: 'Pengaturan Pengambilan', dateTimeFormat: 'MM / DD / YYYY hh: mm A', - desc: 'Uji efek pukulan Pengetahuan berdasarkan teks kueri yang diberikan.', + desc: 'Uji dampak pengetahuan terhadap hasil pencarian berdasarkan teks kueri yang diberikan.', viewDetail: 'Lihat Detail', viewChart: 'Lihat GRAFIK VAKTOR', chunkDetail: 'Detail Potongan', diff --git a/web/i18n/id-ID/dataset-settings.ts b/web/i18n/id-ID/dataset-settings.ts index 247033ecdf..ba29fcf38d 100644 --- a/web/i18n/id-ID/dataset-settings.ts +++ b/web/i18n/id-ID/dataset-settings.ts @@ -3,7 +3,7 @@ const translation = { retrievalSetting: { title: 'Pengaturan Pengambilan', description: 'tentang metode pengambilan.', - longDescription: 'tentang metode pengambilan, Anda dapat mengudagnya kapan saja di pengaturan Pengetahuan.', + longDescription: 'tentang metode pengambilan, Anda dapat mengunduhnya kapan saja di pengaturan Pengetahuan.', method: 'Metode Pengambilan', learnMore: 'Pelajari lebih lanjut', }, diff --git a/web/i18n/id-ID/dataset.ts b/web/i18n/id-ID/dataset.ts index 727dca150e..1a48e623c7 100644 --- a/web/i18n/id-ID/dataset.ts +++ b/web/i18n/id-ID/dataset.ts @@ -133,7 +133,7 @@ const translation = { search: 'Metadata pencarian', }, datasetMetadata: { - disabled: 'Cacat', + disabled: 'Nonaktif', addMetaData: 'Tambahkan Metadata', description: 'Anda dapat mengelola semua metadata dalam pengetahuan ini di sini. Modifikasi akan disinkronkan ke setiap dokumen.', deleteTitle: 'Konfirmasi untuk menghapus', @@ -141,7 +141,7 @@ const translation = { rename: 'Ubah nama', builtInDescription: 'Metadata bawaan secara otomatis diekstrak dan dihasilkan. Itu harus diaktifkan sebelum digunakan dan tidak dapat diedit.', namePlaceholder: 'Nama metadata', - builtIn: 'Built-in', + builtIn: 'Bawaan', }, documentMetadata: { metadataToolTip: 'Metadata berfungsi sebagai filter penting yang meningkatkan akurasi dan relevansi pengambilan informasi. Anda dapat memodifikasi dan menambahkan metadata untuk dokumen ini di sini.', diff --git a/web/i18n/id-ID/education.ts b/web/i18n/id-ID/education.ts index 46232c953e..85f74cc51e 100644 --- a/web/i18n/id-ID/education.ts +++ b/web/i18n/id-ID/education.ts @@ -60,7 +60,7 @@ const translation = { }, dateFormat: 'MM / DD / YYYY', }, - submit: 'Tunduk', + submit: 'Kirim', toVerified: 'Dapatkan Pendidikan Terverifikasi', currentSigned: 'SAAT INI MASUK SEBAGAI', successTitle: 'Anda telah mendapatkan Dify Education Verified', diff --git a/web/i18n/id-ID/explore.ts b/web/i18n/id-ID/explore.ts index c9d22a605b..a482d8f755 100644 --- a/web/i18n/id-ID/explore.ts +++ b/web/i18n/id-ID/explore.ts @@ -1,10 +1,10 @@ const translation = { sidebar: { action: { - unpin: 'Lepaskan pin', - pin: 'Pin', - delete: 'Menghapus', - rename: 'Ubah nama', + unpin: 'Lepaskan sematan', + pin: 'Sematkan', + delete: 'Hapus', + rename: 'Ganti nama', }, delete: { content: 'Apakah Anda yakin ingin menghapus aplikasi ini?', diff --git a/web/i18n/id-ID/login.ts b/web/i18n/id-ID/login.ts index 59306fa310..317c3e7fcd 100644 --- a/web/i18n/id-ID/login.ts +++ b/web/i18n/id-ID/login.ts @@ -36,8 +36,8 @@ const translation = { continueWithCode: 'Lanjutkan dengan kode', sendVerificationCode: 'Kirim Kode Verifikasi', invalidInvitationCode: 'Kode undangan tidak valid', - installBtn: 'Mengatur', - joinTipStart: 'Mengundang Anda bergabung', + installBtn: 'Siapkan', + joinTipStart: 'Mengundang Anda untuk bergabung', or: 'ATAU', namePlaceholder: 'Nama pengguna Anda', withSSO: 'Lanjutkan dengan SSO', @@ -53,23 +53,23 @@ const translation = { invitationCodePlaceholder: 'Kode undangan Anda', emailPlaceholder: 'Email Anda', tos: 'Ketentuan Layanan', - go: 'Pergi ke Dify', + go: 'Buka Dify', forgotPassword: 'Lupa Kata Sandi Anda?', sendUsMail: 'Kirimkan perkenalan Anda melalui email kepada kami, dan kami akan menangani permintaan undangan.', pp: 'Kebijakan Privasi', activatedTipEnd: 'tim', - backToSignIn: 'Kembali untuk login', + backToSignIn: 'Kembali ke halaman masuk', passwordChanged: 'Masuk sekarang', withGitHub: 'Lanjutkan dengan GitHub', accountAlreadyInited: 'Akun sudah diinisialisasi', withGoogle: 'Lanjutkan dengan Google', - rightDesc: 'Bangun aplikasi AI yang menawan secara visual, dapat dioperasikan, dan ditingkatkan dengan mudah.', + rightDesc: 'Bangun aplikasi AI yang menarik secara visual, mudah dioperasikan, dan mudah diskalakan.', invitationCode: 'Kode Undangan', invalidToken: 'Token tidak valid atau kedaluwarsa', setAdminAccount: 'Menyiapkan akun admin', forgotPasswordDesc: 'Silakan masukkan alamat email Anda untuk mengatur ulang kata sandi Anda. Kami akan mengirimi Anda email dengan instruksi tentang cara mengatur ulang kata sandi Anda.', confirmPassword: 'Konfirmasi Kata Sandi', - changePasswordBtn: 'Menetapkan kata sandi', + changePasswordBtn: 'Tetapkan kata sandi', resetPassword: 'Atur Ulang Kata Sandi', explore: 'Jelajahi Dify', useVerificationCode: 'Gunakan Kode Verifikasi', @@ -84,7 +84,7 @@ const translation = { licenseLost: 'Lisensi Hilang', licenseInactive: 'Lisensi Tidak Aktif', enterYourName: 'Silakan masukkan nama pengguna Anda', - back: 'Belakang', + back: 'Kembali', activated: 'Masuk sekarang', goToInit: 'Jika Anda belum menginisialisasi akun, silakan buka halaman inisialisasi', licenseExpired: 'Lisensi Kedaluwarsa', @@ -94,9 +94,9 @@ const translation = { validate: 'Memvalidasi', resetPasswordDesc: 'Ketik email yang Anda gunakan untuk mendaftar di Dify dan kami akan mengirimkan email reset kata sandi kepada Anda.', licenseLostTip: 'Gagal menghubungkan server lisensi Dify. Hubungi administrator Anda untuk terus menggunakan Dify.', - signBtn: 'Tandatangan', + signBtn: 'Masuk', sendResetLink: 'Kirim tautan reset', - createAndSignIn: 'Membuat dan masuk', + createAndSignIn: 'Buat dan masuk', licenseExpiredTip: 'Lisensi Dify Enterprise untuk ruang kerja Anda telah kedaluwarsa. Hubungi administrator Anda untuk terus menggunakan Dify.', email: 'Alamat email', noLoginMethodTip: 'Silakan hubungi admin sistem untuk menambahkan metode autentikasi.', @@ -104,11 +104,11 @@ const translation = { licenseInactiveTip: 'Lisensi Dify Enterprise untuk ruang kerja Anda tidak aktif. Hubungi administrator Anda untuk terus menggunakan Dify.', rightTitle: 'Buka potensi penuh LLM', welcome: '👋 Selamat datang di Dify, silakan login untuk melanjutkan.', - changePassword: 'Menetapkan kata sandi', - setAdminAccountDesc: 'Hak istimewa maksimum untuk akun admin, yang dapat digunakan untuk membuat aplikasi dan mengelola penyedia LLM, dll.', - join: 'Ikat', + changePassword: 'Ubah kata sandi', + setAdminAccountDesc: 'Akun admin memiliki hak istimewa penuh untuk membuat aplikasi, mengelola penyedia LLM, dll.', + join: 'Gabung', forget: 'Lupa Kata Sandi Anda?', - backToLogin: 'Kembali ke login', + backToLogin: 'Kembali ke halaman masuk', oneMoreStep: 'Satu langkah lagi', } diff --git a/web/i18n/id-ID/oauth.ts b/web/i18n/id-ID/oauth.ts index c12c4161c4..933fcb5525 100644 --- a/web/i18n/id-ID/oauth.ts +++ b/web/i18n/id-ID/oauth.ts @@ -17,11 +17,11 @@ const translation = { authorizeFailed: 'Otorisasi gagal', authAppInfoFetchFailed: 'Gagal mengambil info aplikasi untuk otorisasi', }, - continue: 'Terus', - unknownApp: 'Aplikasi Tidak Dikenal', - login: 'Login', - connect: 'Hubungkan ke', - switchAccount: 'Beralih Akun', + continue: 'Lanjut', + unknownApp: 'Aplikasi tidak dikenal', + login: 'Masuk', + connect: 'Hubungkan', + switchAccount: 'Ganti Akun', } export default translation diff --git a/web/i18n/id-ID/plugin.ts b/web/i18n/id-ID/plugin.ts index ed50a203c2..c9b9b939d8 100644 --- a/web/i18n/id-ID/plugin.ts +++ b/web/i18n/id-ID/plugin.ts @@ -39,7 +39,7 @@ const translation = { local: 'Plugin Lokal', }, operation: { - remove: 'Buka', + remove: 'Hapus', info: 'Plugin Info', update: 'Pemutakhiran', detail: 'Rincian', @@ -55,7 +55,7 @@ const translation = { empty: 'Klik tombol \' \' untuk menambahkan alat. Anda dapat menambahkan beberapa alat.', params: 'KONFIGURASI PENALARAN', unsupportedMCPTool: 'Saat ini versi plugin strategi agen yang dipilih tidak mendukung alat MCP.', - auto: 'Mobil', + auto: 'Otomatis', descriptionPlaceholder: 'Deskripsi singkat tentang tujuan alat, misalnya, mendapatkan suhu untuk lokasi tertentu.', toolSetting: 'Pengaturan Alat', settings: 'PENGATURAN PENGGUNA', @@ -174,11 +174,11 @@ const translation = { installing: 'Menginstal...', uploadFailed: 'Upload gagal', pluginLoadErrorDesc: 'Plugin ini tidak akan diinstal', - next: 'Depan', + next: 'Lanjut', installedSuccessfully: 'Instalasi berhasil', install: 'Pasang', installFailed: 'Instalasi gagal', - back: 'Belakang', + back: 'Kembali', readyToInstallPackage: 'Tentang menginstal plugin berikut', installedSuccessfullyDesc: 'Plugin telah berhasil diinstal.', pluginLoadError: 'Kesalahan pemuatan plugin', @@ -227,7 +227,7 @@ const translation = { empower: 'Berdayakan pengembangan AI Anda', partnerTip: 'Diverifikasi oleh partner Dify', moreFrom: 'Selengkapnya dari Marketplace', - sortBy: 'Kota hitam', + sortBy: 'Urutkan berdasarkan', and: 'dan', difyMarketplace: 'Dify Marketplace', verifiedTip: 'Diverifikasi oleh Dify', diff --git a/web/i18n/id-ID/time.ts b/web/i18n/id-ID/time.ts index d6ed8813e1..6e06130c7b 100644 --- a/web/i18n/id-ID/time.ts +++ b/web/i18n/id-ID/time.ts @@ -1,17 +1,17 @@ const translation = { daysInWeek: { - Wed: 'Bertaruh', + Wed: 'Rabu', Thu: 'Kamis', - Sun: 'Matahari', - Tue: 'Membunuh', - Mon: 'Mon', - Sat: 'Hari sabtu', - Fri: 'Bebas', + Sun: 'Minggu', + Tue: 'Selasa', + Mon: 'Senin', + Sat: 'Sabtu', + Fri: 'Jumat', }, months: { August: 'Agustus', October: 'Oktober', - May: 'Menjahit', + May: 'Mei', September: 'September', December: 'Desember', November: 'November', @@ -34,7 +34,7 @@ const translation = { dateFormats: { display: 'MMMM D, YYYY', input: 'YYYY-MM-DD', - outputWithTime: 'YYYY-MM-DDTHH:mm:ss. SSSZ', + outputWithTime: 'YYYY-MM-DDTHH:mm:ss.SSSZ', output: 'YYYY-MM-DD', displayWithTime: 'MMMM D, YYYY hh:mm A', }, diff --git a/web/i18n/id-ID/workflow.ts b/web/i18n/id-ID/workflow.ts index 57b138b2e2..e2daef6f7a 100644 --- a/web/i18n/id-ID/workflow.ts +++ b/web/i18n/id-ID/workflow.ts @@ -14,7 +14,7 @@ const translation = { title: 'Tarik', }, }, - undo: 'Buka', + undo: 'Urungkan', embedIntoSite: 'Sematkan ke Situs', editing: 'Mengedit', inRunMode: 'Dalam Mode Jalankan', @@ -33,10 +33,10 @@ const translation = { addParallelNode: 'Tambahkan Node Paralel', onFailure: 'Pada Kegagalan', update: 'Pemutakhiran', - parallelRun: 'Lari Paralel', - configure: 'Mengkonfigurasi', + parallelRun: 'Jalankan Paralel', + configure: 'Konfigurasikan', copy: 'Menyalin', - redo: 'Siap', + redo: 'Ulangi', runApp: 'Jalankan Aplikasi', noHistory: 'Tidak Ada Sejarah', importDSLTip: 'Draf saat ini akan ditimpa.\nEkspor alur kerja sebagai cadangan sebelum mengimpor.', @@ -54,7 +54,7 @@ const translation = { importSuccess: 'Berhasil Impor', jumpToNode: 'Lompat ke simpul ini', tagBound: 'Jumlah aplikasi yang menggunakan tag ini', - model: 'Pola', + model: 'Model', workflowAsToolTip: 'Konfigurasi ulang alat diperlukan setelah pembaruan alur kerja.', currentDraft: 'Draf Saat Ini', parallel: 'SEJAJAR', @@ -65,7 +65,7 @@ const translation = { importWarning: 'Hati', running: 'Menjalankan', publishedAt: 'Diterbitkan', - run: 'Lari', + run: 'Jalankan', importDSL: 'Impor DSL', featuresDescription: 'Tingkatkan pengalaman pengguna aplikasi web', inPreviewMode: 'Dalam Mode Pratinjau', @@ -168,9 +168,9 @@ const translation = { nodeAdd: 'Node ditambahkan', nodePaste: 'Node ditempelkan', noteDelete: 'Catatan dihapus', - hint: 'Indian', + hint: 'Petunjuk', nodeTitleChange: 'Judul simpul diubah', - title: 'Perubahan Riwayat', + title: 'Riwayat Perubahan', nodeDescriptionChange: 'Deskripsi simpul diubah', clearHistory: 'Hapus Sejarah', placeholder: 'Anda belum mengubah apa pun', @@ -189,7 +189,7 @@ const translation = { errorMsg: { fields: { variable: 'Nama Variabel', - model: 'Pola', + model: 'Model', rerankModel: 'Model Peringkat Ulang yang dikonfigurasi', visionVariable: 'Variabel Penglihatan', variableValue: 'Nilai Variabel', @@ -238,11 +238,11 @@ const translation = { 'question-classifier': 'Pengklasifikasi Pertanyaan', 'iteration-start': 'Iterasi Mulai', 'knowledge-retrieval': 'Pengambilan Pengetahuan', - 'loop': 'Lari', + 'loop': 'Perulangan', 'assigner': 'Penerima Variabel', 'agent': 'Agen', 'list-operator': 'Operator Daftar', - 'answer': 'Menjawab', + 'answer': 'Jawaban', 'parameter-extractor': 'Ekstraktor Parameter', 'document-extractor': 'Ekstraktor Dokumen', 'end': 'Ujung', @@ -286,10 +286,10 @@ const translation = { horizontal: 'Horisontal', distributeHorizontal: 'Spasi Secara Horizontal', zoomTo100: 'Perbesar hingga 100%', - alignLeft: 'Kiri', + alignLeft: 'Rata Kiri', distributeVertical: 'Ruang Secara Vertikal', zoomTo50: 'Perbesar hingga 50%', - alignBottom: 'Dasar', + alignBottom: 'Rata Bawah', }, variableReference: { conversationVars: 'variabel percakapan', diff --git a/web/i18n/tr-TR/common.ts b/web/i18n/tr-TR/common.ts index 2ecd18f787..84646f7dec 100644 --- a/web/i18n/tr-TR/common.ts +++ b/web/i18n/tr-TR/common.ts @@ -746,7 +746,7 @@ const translation = { content: 'Geri Bildirim İçeriği', subtitle: 'Lütfen bu yanıtla ilgili neyin yanlış gittiğini bize bildirin', title: 'Geri Bildirim Sağla', - placeholder: 'Lütfen neyin yanlış gittiğini veya nasıl iyileşebileceğimizı açıklayın...', + placeholder: 'Lütfen neyin yanlış gittiğini veya nasıl iyileşebileceğimizi açıklayın...', }, } diff --git a/web/i18n/uk-UA/common.ts b/web/i18n/uk-UA/common.ts index bff6634aff..f8e54f8427 100644 --- a/web/i18n/uk-UA/common.ts +++ b/web/i18n/uk-UA/common.ts @@ -747,7 +747,7 @@ const translation = { title: 'Надати відгук', content: 'Зміст відгуку', placeholder: 'Будь ласка, опишіть, що пішло не так або як ми можемо покращити...', - subtitle: 'Будь ласка, скажіть нам, що пішло не так з цим відповіді', + subtitle: 'Будь ласка, скажіть нам, що пішло не так із цією відповіддю', }, } From a7627882a787d0172821f7919df88c3fe23276ac Mon Sep 17 00:00:00 2001 From: 17hz <0x149527@gmail.com> Date: Wed, 3 Sep 2025 15:39:09 +0800 Subject: [PATCH 06/15] fix: Boolean type control is not displayed (#25031) Co-authored-by: WTW0313 --- .../account-setting/model-provider-page/declarations.ts | 2 +- .../workflow/nodes/_base/components/form-input-item.tsx | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/web/app/components/header/account-setting/model-provider-page/declarations.ts b/web/app/components/header/account-setting/model-provider-page/declarations.ts index 9fac34b21b..62cb1a96e9 100644 --- a/web/app/components/header/account-setting/model-provider-page/declarations.ts +++ b/web/app/components/header/account-setting/model-provider-page/declarations.ts @@ -14,7 +14,7 @@ export enum FormTypeEnum { secretInput = 'secret-input', select = 'select', radio = 'radio', - boolean = 'boolean', + boolean = 'checkbox', files = 'files', file = 'file', modelSelector = 'model-selector', diff --git a/web/app/components/workflow/nodes/_base/components/form-input-item.tsx b/web/app/components/workflow/nodes/_base/components/form-input-item.tsx index d624130317..a7825145b4 100644 --- a/web/app/components/workflow/nodes/_base/components/form-input-item.tsx +++ b/web/app/components/workflow/nodes/_base/components/form-input-item.tsx @@ -90,8 +90,8 @@ const FormInputItem: FC = ({ // return VarType.appSelector // else if (isModelSelector) // return VarType.modelSelector - // else if (isBoolean) - // return VarType.boolean + else if (isBoolean) + return VarType.boolean else if (isObject) return VarType.object else if (isArray) @@ -183,7 +183,7 @@ const FormInputItem: FC = ({ return (
{showTypeSwitch && ( - + )} {isString && ( = ({ placeholder={placeholder?.[language] || placeholder?.en_US} /> )} - {isBoolean && ( + {isBoolean && isConstant && ( Date: Wed, 3 Sep 2025 16:22:13 +0800 Subject: [PATCH 07/15] Fix advanced chat workflow event handler signature mismatch (#25078) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- Makefile | 2 +- api/core/app/apps/advanced_chat/generate_task_pipeline.py | 2 +- api/extensions/storage/clickzetta_volume/file_lifecycle.py | 5 +++-- .../storage/clickzetta_volume/volume_permissions.py | 3 ++- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 388c367fdf..d82f6f24ad 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ prepare-web: prepare-api: @echo "🔧 Setting up API environment..." @cp -n api/.env.example api/.env 2>/dev/null || echo "API .env already exists" - @cd api && uv sync --dev --extra all + @cd api && uv sync --dev @cd api && uv run flask db upgrade @echo "✅ API environment prepared (not started)" diff --git a/api/core/app/apps/advanced_chat/generate_task_pipeline.py b/api/core/app/apps/advanced_chat/generate_task_pipeline.py index 2f0e4ef319..750e13c502 100644 --- a/api/core/app/apps/advanced_chat/generate_task_pipeline.py +++ b/api/core/app/apps/advanced_chat/generate_task_pipeline.py @@ -310,7 +310,7 @@ class AdvancedChatAppGenerateTaskPipeline: err = self._base_task_pipeline._handle_error(event=event, session=session, message_id=self._message_id) yield self._base_task_pipeline._error_to_stream_response(err) - def _handle_workflow_started_event(self, **kwargs) -> Generator[StreamResponse, None, None]: + def _handle_workflow_started_event(self, *args, **kwargs) -> Generator[StreamResponse, None, None]: """Handle workflow started events.""" with self._database_session() as session: workflow_execution = self._workflow_cycle_manager.handle_workflow_run_start() diff --git a/api/extensions/storage/clickzetta_volume/file_lifecycle.py b/api/extensions/storage/clickzetta_volume/file_lifecycle.py index 29210dd0f0..f5d6fd6f22 100644 --- a/api/extensions/storage/clickzetta_volume/file_lifecycle.py +++ b/api/extensions/storage/clickzetta_volume/file_lifecycle.py @@ -1,7 +1,8 @@ """ClickZetta Volume file lifecycle management -This module provides file lifecycle management features including version control, automatic cleanup, backup and restore. -Supports complete lifecycle management for knowledge base files. +This module provides file lifecycle management features including version control, +automatic cleanup, backup and restore. Supports complete lifecycle management for +knowledge base files. """ import json diff --git a/api/extensions/storage/clickzetta_volume/volume_permissions.py b/api/extensions/storage/clickzetta_volume/volume_permissions.py index e9503595af..d216790f17 100644 --- a/api/extensions/storage/clickzetta_volume/volume_permissions.py +++ b/api/extensions/storage/clickzetta_volume/volume_permissions.py @@ -121,7 +121,8 @@ class VolumePermissionManager: except Exception: logger.exception("User Volume permission check failed") - # For User Volume, if permission check fails, it might be a configuration issue, provide friendlier error message + # For User Volume, if permission check fails, it might be a configuration issue, + # provide friendlier error message logger.info("User Volume permission check failed, but permission checking is disabled in this version") return False From 67cc70ad6146ae84f78fb96bfc1e8c3f3d1d981e Mon Sep 17 00:00:00 2001 From: zxhlyh Date: Wed, 3 Sep 2025 18:23:57 +0800 Subject: [PATCH 08/15] fix: model credential name (#25081) Co-authored-by: hjlarry Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- api/core/entities/provider_configuration.py | 16 ++++++++-------- .../model-provider-page/model-modal/index.tsx | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/api/core/entities/provider_configuration.py b/api/core/entities/provider_configuration.py index b74e081dd4..9119462aca 100644 --- a/api/core/entities/provider_configuration.py +++ b/api/core/entities/provider_configuration.py @@ -410,10 +410,9 @@ class ProviderConfiguration(BaseModel): :return: """ with Session(db.engine) as session: - if credential_name and self._check_provider_credential_name_exists( - credential_name=credential_name, session=session - ): - raise ValueError(f"Credential with name '{credential_name}' already exists.") + if credential_name: + if self._check_provider_credential_name_exists(credential_name=credential_name, session=session): + raise ValueError(f"Credential with name '{credential_name}' already exists.") else: credential_name = self._generate_provider_credential_name(session) @@ -890,10 +889,11 @@ class ProviderConfiguration(BaseModel): :return: """ with Session(db.engine) as session: - if credential_name and self._check_custom_model_credential_name_exists( - model=model, model_type=model_type, credential_name=credential_name, session=session - ): - raise ValueError(f"Model credential with name '{credential_name}' already exists for {model}.") + if credential_name: + if self._check_custom_model_credential_name_exists( + model=model, model_type=model_type, credential_name=credential_name, session=session + ): + raise ValueError(f"Model credential with name '{credential_name}' already exists for {model}.") else: credential_name = self._generate_custom_model_credential_name( model=model, model_type=model_type, session=session diff --git a/web/app/components/header/account-setting/model-provider-page/model-modal/index.tsx b/web/app/components/header/account-setting/model-provider-page/model-modal/index.tsx index adf633831b..4ffbc8f191 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-modal/index.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-modal/index.tsx @@ -115,7 +115,7 @@ const ModelModal: FC = ({ const [selectedCredential, setSelectedCredential] = useState() const formRef2 = useRef(null) const isEditMode = !!Object.keys(formValues).filter((key) => { - return key !== '__model_name' && key !== '__model_type' + return key !== '__model_name' && key !== '__model_type' && !!formValues[key] }).length && isCurrentWorkspaceManager const handleSave = useCallback(async () => { @@ -167,7 +167,7 @@ const ModelModal: FC = ({ __authorization_name__, ...rest } = values - if (__model_name && __model_type && __authorization_name__) { + if (__model_name && __model_type) { await handleSaveCredential({ credential_id: credential?.credential_id, credentials: rest, From d011ddfc643a49369e5f1021d7a45e56b97eeb33 Mon Sep 17 00:00:00 2001 From: Stream Date: Wed, 3 Sep 2025 18:54:07 +0800 Subject: [PATCH 09/15] chore(version): bump version to 1.8.1 (#25060) --- api/pyproject.toml | 2 +- api/uv.lock | 2 +- docker/docker-compose-template.yaml | 2 +- docker/docker-compose.yaml | 2 +- web/package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/api/pyproject.toml b/api/pyproject.toml index d6f74fc510..a0c108cd2c 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "dify-api" -version = "1.8.0" +version = "1.8.1" requires-python = ">=3.11,<3.13" dependencies = [ diff --git a/api/uv.lock b/api/uv.lock index 32254faa8e..7e67a84ce2 100644 --- a/api/uv.lock +++ b/api/uv.lock @@ -1260,7 +1260,7 @@ wheels = [ [[package]] name = "dify-api" -version = "1.8.0" +version = "1.8.1" source = { virtual = "." } dependencies = [ { name = "arize-phoenix-otel" }, diff --git a/docker/docker-compose-template.yaml b/docker/docker-compose-template.yaml index a779999983..e6f76e1fb4 100644 --- a/docker/docker-compose-template.yaml +++ b/docker/docker-compose-template.yaml @@ -2,7 +2,7 @@ x-shared-env: &shared-api-worker-env services: # API service api: - image: langgenius/dify-api:1.8.0 + image: langgenius/dify-api:1.8.1 restart: always environment: # Use the shared environment variables. diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index bd668be17f..a451a114bc 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -582,7 +582,7 @@ x-shared-env: &shared-api-worker-env services: # API service api: - image: langgenius/dify-api:1.8.0 + image: langgenius/dify-api:1.8.1 restart: always environment: # Use the shared environment variables. diff --git a/web/package.json b/web/package.json index e82b41636c..e64d548824 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "dify-web", - "version": "1.8.0", + "version": "1.8.1", "private": true, "packageManager": "pnpm@10.15.0", "engines": { From c7700ac1762a4feccf60211d3dca3e39ec65a83c Mon Sep 17 00:00:00 2001 From: -LAN- Date: Wed, 3 Sep 2025 20:25:44 +0800 Subject: [PATCH 10/15] chore(docker): bump version (#25092) Signed-off-by: -LAN- --- docker/docker-compose-template.yaml | 107 ++++++++++++++++++---------- docker/docker-compose.yaml | 107 ++++++++++++++++++---------- 2 files changed, 140 insertions(+), 74 deletions(-) diff --git a/docker/docker-compose-template.yaml b/docker/docker-compose-template.yaml index e6f76e1fb4..b479795c93 100644 --- a/docker/docker-compose-template.yaml +++ b/docker/docker-compose-template.yaml @@ -31,7 +31,7 @@ services: # worker service # The Celery worker for processing the queue. worker: - image: langgenius/dify-api:1.8.0 + image: langgenius/dify-api:1.8.1 restart: always environment: # Use the shared environment variables. @@ -58,7 +58,7 @@ services: # worker_beat service # Celery beat for scheduling periodic tasks. worker_beat: - image: langgenius/dify-api:1.8.0 + image: langgenius/dify-api:1.8.1 restart: always environment: # Use the shared environment variables. @@ -76,7 +76,7 @@ services: # Frontend web application. web: - image: langgenius/dify-web:1.8.0 + image: langgenius/dify-web:1.8.1 restart: always environment: CONSOLE_API_URL: ${CONSOLE_API_URL:-} @@ -118,7 +118,17 @@ services: volumes: - ./volumes/db/data:/var/lib/postgresql/data healthcheck: - test: [ 'CMD', 'pg_isready', '-h', 'db', '-U', '${PGUSER:-postgres}', '-d', '${POSTGRES_DB:-dify}' ] + test: + [ + "CMD", + "pg_isready", + "-h", + "db", + "-U", + "${PGUSER:-postgres}", + "-d", + "${POSTGRES_DB:-dify}", + ] interval: 1s timeout: 3s retries: 60 @@ -135,7 +145,11 @@ services: # Set the redis password when startup redis server. command: redis-server --requirepass ${REDIS_PASSWORD:-difyai123456} healthcheck: - test: [ 'CMD-SHELL', 'redis-cli -a ${REDIS_PASSWORD:-difyai123456} ping | grep -q PONG' ] + test: + [ + "CMD-SHELL", + "redis-cli -a ${REDIS_PASSWORD:-difyai123456} ping | grep -q PONG", + ] # The DifySandbox sandbox: @@ -157,7 +171,7 @@ services: - ./volumes/sandbox/dependencies:/dependencies - ./volumes/sandbox/conf:/conf healthcheck: - test: [ 'CMD', 'curl', '-f', 'http://localhost:8194/health' ] + test: ["CMD", "curl", "-f", "http://localhost:8194/health"] networks: - ssrf_proxy_network @@ -231,7 +245,12 @@ services: volumes: - ./ssrf_proxy/squid.conf.template:/etc/squid/squid.conf.template - ./ssrf_proxy/docker-entrypoint.sh:/docker-entrypoint-mount.sh - entrypoint: [ 'sh', '-c', "cp /docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh" ] + entrypoint: + [ + "sh", + "-c", + "cp /docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh", + ] environment: # pls clearly modify the squid env vars to fit your network environment. HTTP_PORT: ${SSRF_HTTP_PORT:-3128} @@ -260,8 +279,8 @@ services: - CERTBOT_EMAIL=${CERTBOT_EMAIL} - CERTBOT_DOMAIN=${CERTBOT_DOMAIN} - CERTBOT_OPTIONS=${CERTBOT_OPTIONS:-} - entrypoint: [ '/docker-entrypoint.sh' ] - command: [ 'tail', '-f', '/dev/null' ] + entrypoint: ["/docker-entrypoint.sh"] + command: ["tail", "-f", "/dev/null"] # The nginx reverse proxy. # used for reverse proxying the API service and Web service. @@ -278,7 +297,12 @@ services: - ./volumes/certbot/conf/live:/etc/letsencrypt/live # cert dir (with certbot container) - ./volumes/certbot/conf:/etc/letsencrypt - ./volumes/certbot/www:/var/www/html - entrypoint: [ 'sh', '-c', "cp /docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh" ] + entrypoint: + [ + "sh", + "-c", + "cp /docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh", + ] environment: NGINX_SERVER_NAME: ${NGINX_SERVER_NAME:-_} NGINX_HTTPS_ENABLED: ${NGINX_HTTPS_ENABLED:-false} @@ -300,14 +324,14 @@ services: - api - web ports: - - '${EXPOSE_NGINX_PORT:-80}:${NGINX_PORT:-80}' - - '${EXPOSE_NGINX_SSL_PORT:-443}:${NGINX_SSL_PORT:-443}' + - "${EXPOSE_NGINX_PORT:-80}:${NGINX_PORT:-80}" + - "${EXPOSE_NGINX_SSL_PORT:-443}:${NGINX_SSL_PORT:-443}" # The Weaviate vector store. weaviate: image: semitechnologies/weaviate:1.19.0 profiles: - - '' + - "" - weaviate restart: always volumes: @@ -360,13 +384,17 @@ services: working_dir: /opt/couchbase stdin_open: true tty: true - entrypoint: [ "" ] + entrypoint: [""] command: sh -c "/opt/couchbase/init/init-cbserver.sh" volumes: - ./volumes/couchbase/data:/opt/couchbase/var/lib/couchbase/data healthcheck: # ensure bucket was created before proceeding - test: [ "CMD-SHELL", "curl -s -f -u Administrator:password http://localhost:8091/pools/default/buckets | grep -q '\\[{' || exit 1" ] + test: + [ + "CMD-SHELL", + "curl -s -f -u Administrator:password http://localhost:8091/pools/default/buckets | grep -q '\\[{' || exit 1", + ] interval: 10s retries: 10 start_period: 30s @@ -392,9 +420,9 @@ services: volumes: - ./volumes/pgvector/data:/var/lib/postgresql/data - ./pgvector/docker-entrypoint.sh:/docker-entrypoint.sh - entrypoint: [ '/docker-entrypoint.sh' ] + entrypoint: ["/docker-entrypoint.sh"] healthcheck: - test: [ 'CMD', 'pg_isready' ] + test: ["CMD", "pg_isready"] interval: 1s timeout: 3s retries: 30 @@ -411,14 +439,14 @@ services: - VB_USERNAME=dify - VB_PASSWORD=Difyai123456 ports: - - '5434:5432' + - "5434:5432" volumes: - ./vastbase/lic:/home/vastbase/vastbase/lic - ./vastbase/data:/home/vastbase/data - ./vastbase/backup:/home/vastbase/backup - ./vastbase/backup_log:/home/vastbase/backup_log healthcheck: - test: [ 'CMD', 'pg_isready' ] + test: ["CMD", "pg_isready"] interval: 1s timeout: 3s retries: 30 @@ -440,7 +468,7 @@ services: volumes: - ./volumes/pgvecto_rs/data:/var/lib/postgresql/data healthcheck: - test: [ 'CMD', 'pg_isready' ] + test: ["CMD", "pg_isready"] interval: 1s timeout: 3s retries: 30 @@ -479,7 +507,11 @@ services: ports: - "${OCEANBASE_VECTOR_PORT:-2881}:2881" healthcheck: - test: [ 'CMD-SHELL', 'obclient -h127.0.0.1 -P2881 -uroot@test -p$${OB_TENANT_PASSWORD} -e "SELECT 1;"' ] + test: + [ + "CMD-SHELL", + 'obclient -h127.0.0.1 -P2881 -uroot@test -p$${OB_TENANT_PASSWORD} -e "SELECT 1;"', + ] interval: 10s retries: 30 start_period: 30s @@ -515,7 +547,7 @@ services: - ./volumes/milvus/etcd:/etcd command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd healthcheck: - test: [ 'CMD', 'etcdctl', 'endpoint', 'health' ] + test: ["CMD", "etcdctl", "endpoint", "health"] interval: 30s timeout: 20s retries: 3 @@ -534,7 +566,7 @@ services: - ./volumes/milvus/minio:/minio_data command: minio server /minio_data --console-address ":9001" healthcheck: - test: [ 'CMD', 'curl', '-f', 'http://localhost:9000/minio/health/live' ] + test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] interval: 30s timeout: 20s retries: 3 @@ -546,7 +578,7 @@ services: image: milvusdb/milvus:v2.5.15 profiles: - milvus - command: [ 'milvus', 'run', 'standalone' ] + command: ["milvus", "run", "standalone"] environment: ETCD_ENDPOINTS: ${ETCD_ENDPOINTS:-etcd:2379} MINIO_ADDRESS: ${MINIO_ADDRESS:-minio:9000} @@ -554,7 +586,7 @@ services: volumes: - ./volumes/milvus/milvus:/var/lib/milvus healthcheck: - test: [ 'CMD', 'curl', '-f', 'http://localhost:9091/healthz' ] + test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"] interval: 30s start_period: 90s timeout: 20s @@ -620,7 +652,7 @@ services: volumes: - ./volumes/opengauss/data:/var/lib/opengauss/data healthcheck: - test: [ "CMD-SHELL", "netstat -lntp | grep tcp6 > /dev/null 2>&1" ] + test: ["CMD-SHELL", "netstat -lntp | grep tcp6 > /dev/null 2>&1"] interval: 10s timeout: 10s retries: 10 @@ -673,18 +705,19 @@ services: node.name: dify-es0 discovery.type: single-node xpack.license.self_generated.type: basic - xpack.security.enabled: 'true' - xpack.security.enrollment.enabled: 'false' - xpack.security.http.ssl.enabled: 'false' + xpack.security.enabled: "true" + xpack.security.enrollment.enabled: "false" + xpack.security.http.ssl.enabled: "false" ports: - ${ELASTICSEARCH_PORT:-9200}:9200 deploy: resources: limits: memory: 2g - entrypoint: [ 'sh', '-c', "sh /docker-entrypoint-mount.sh" ] + entrypoint: ["sh", "-c", "sh /docker-entrypoint-mount.sh"] healthcheck: - test: [ 'CMD', 'curl', '-s', 'http://localhost:9200/_cluster/health?pretty' ] + test: + ["CMD", "curl", "-s", "http://localhost:9200/_cluster/health?pretty"] interval: 30s timeout: 10s retries: 50 @@ -702,17 +735,17 @@ services: environment: XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY: d1a66dfd-c4d3-4a0a-8290-2abcb83ab3aa NO_PROXY: localhost,127.0.0.1,elasticsearch,kibana - XPACK_SECURITY_ENABLED: 'true' - XPACK_SECURITY_ENROLLMENT_ENABLED: 'false' - XPACK_SECURITY_HTTP_SSL_ENABLED: 'false' - XPACK_FLEET_ISAIRGAPPED: 'true' + XPACK_SECURITY_ENABLED: "true" + XPACK_SECURITY_ENROLLMENT_ENABLED: "false" + XPACK_SECURITY_HTTP_SSL_ENABLED: "false" + XPACK_FLEET_ISAIRGAPPED: "true" I18N_LOCALE: zh-CN - SERVER_PORT: '5601' + SERVER_PORT: "5601" ELASTICSEARCH_HOSTS: http://elasticsearch:9200 ports: - ${KIBANA_PORT:-5601}:5601 healthcheck: - test: [ 'CMD-SHELL', 'curl -s http://localhost:5601 >/dev/null || exit 1' ] + test: ["CMD-SHELL", "curl -s http://localhost:5601 >/dev/null || exit 1"] interval: 30s timeout: 10s retries: 3 diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index a451a114bc..9774df3df5 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -611,7 +611,7 @@ services: # worker service # The Celery worker for processing the queue. worker: - image: langgenius/dify-api:1.8.0 + image: langgenius/dify-api:1.8.1 restart: always environment: # Use the shared environment variables. @@ -638,7 +638,7 @@ services: # worker_beat service # Celery beat for scheduling periodic tasks. worker_beat: - image: langgenius/dify-api:1.8.0 + image: langgenius/dify-api:1.8.1 restart: always environment: # Use the shared environment variables. @@ -656,7 +656,7 @@ services: # Frontend web application. web: - image: langgenius/dify-web:1.8.0 + image: langgenius/dify-web:1.8.1 restart: always environment: CONSOLE_API_URL: ${CONSOLE_API_URL:-} @@ -698,7 +698,17 @@ services: volumes: - ./volumes/db/data:/var/lib/postgresql/data healthcheck: - test: [ 'CMD', 'pg_isready', '-h', 'db', '-U', '${PGUSER:-postgres}', '-d', '${POSTGRES_DB:-dify}' ] + test: + [ + "CMD", + "pg_isready", + "-h", + "db", + "-U", + "${PGUSER:-postgres}", + "-d", + "${POSTGRES_DB:-dify}", + ] interval: 1s timeout: 3s retries: 60 @@ -715,7 +725,11 @@ services: # Set the redis password when startup redis server. command: redis-server --requirepass ${REDIS_PASSWORD:-difyai123456} healthcheck: - test: [ 'CMD-SHELL', 'redis-cli -a ${REDIS_PASSWORD:-difyai123456} ping | grep -q PONG' ] + test: + [ + "CMD-SHELL", + "redis-cli -a ${REDIS_PASSWORD:-difyai123456} ping | grep -q PONG", + ] # The DifySandbox sandbox: @@ -737,7 +751,7 @@ services: - ./volumes/sandbox/dependencies:/dependencies - ./volumes/sandbox/conf:/conf healthcheck: - test: [ 'CMD', 'curl', '-f', 'http://localhost:8194/health' ] + test: ["CMD", "curl", "-f", "http://localhost:8194/health"] networks: - ssrf_proxy_network @@ -811,7 +825,12 @@ services: volumes: - ./ssrf_proxy/squid.conf.template:/etc/squid/squid.conf.template - ./ssrf_proxy/docker-entrypoint.sh:/docker-entrypoint-mount.sh - entrypoint: [ 'sh', '-c', "cp /docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh" ] + entrypoint: + [ + "sh", + "-c", + "cp /docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh", + ] environment: # pls clearly modify the squid env vars to fit your network environment. HTTP_PORT: ${SSRF_HTTP_PORT:-3128} @@ -840,8 +859,8 @@ services: - CERTBOT_EMAIL=${CERTBOT_EMAIL} - CERTBOT_DOMAIN=${CERTBOT_DOMAIN} - CERTBOT_OPTIONS=${CERTBOT_OPTIONS:-} - entrypoint: [ '/docker-entrypoint.sh' ] - command: [ 'tail', '-f', '/dev/null' ] + entrypoint: ["/docker-entrypoint.sh"] + command: ["tail", "-f", "/dev/null"] # The nginx reverse proxy. # used for reverse proxying the API service and Web service. @@ -858,7 +877,12 @@ services: - ./volumes/certbot/conf/live:/etc/letsencrypt/live # cert dir (with certbot container) - ./volumes/certbot/conf:/etc/letsencrypt - ./volumes/certbot/www:/var/www/html - entrypoint: [ 'sh', '-c', "cp /docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh" ] + entrypoint: + [ + "sh", + "-c", + "cp /docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh", + ] environment: NGINX_SERVER_NAME: ${NGINX_SERVER_NAME:-_} NGINX_HTTPS_ENABLED: ${NGINX_HTTPS_ENABLED:-false} @@ -880,14 +904,14 @@ services: - api - web ports: - - '${EXPOSE_NGINX_PORT:-80}:${NGINX_PORT:-80}' - - '${EXPOSE_NGINX_SSL_PORT:-443}:${NGINX_SSL_PORT:-443}' + - "${EXPOSE_NGINX_PORT:-80}:${NGINX_PORT:-80}" + - "${EXPOSE_NGINX_SSL_PORT:-443}:${NGINX_SSL_PORT:-443}" # The Weaviate vector store. weaviate: image: semitechnologies/weaviate:1.19.0 profiles: - - '' + - "" - weaviate restart: always volumes: @@ -940,13 +964,17 @@ services: working_dir: /opt/couchbase stdin_open: true tty: true - entrypoint: [ "" ] + entrypoint: [""] command: sh -c "/opt/couchbase/init/init-cbserver.sh" volumes: - ./volumes/couchbase/data:/opt/couchbase/var/lib/couchbase/data healthcheck: # ensure bucket was created before proceeding - test: [ "CMD-SHELL", "curl -s -f -u Administrator:password http://localhost:8091/pools/default/buckets | grep -q '\\[{' || exit 1" ] + test: + [ + "CMD-SHELL", + "curl -s -f -u Administrator:password http://localhost:8091/pools/default/buckets | grep -q '\\[{' || exit 1", + ] interval: 10s retries: 10 start_period: 30s @@ -972,9 +1000,9 @@ services: volumes: - ./volumes/pgvector/data:/var/lib/postgresql/data - ./pgvector/docker-entrypoint.sh:/docker-entrypoint.sh - entrypoint: [ '/docker-entrypoint.sh' ] + entrypoint: ["/docker-entrypoint.sh"] healthcheck: - test: [ 'CMD', 'pg_isready' ] + test: ["CMD", "pg_isready"] interval: 1s timeout: 3s retries: 30 @@ -991,14 +1019,14 @@ services: - VB_USERNAME=dify - VB_PASSWORD=Difyai123456 ports: - - '5434:5432' + - "5434:5432" volumes: - ./vastbase/lic:/home/vastbase/vastbase/lic - ./vastbase/data:/home/vastbase/data - ./vastbase/backup:/home/vastbase/backup - ./vastbase/backup_log:/home/vastbase/backup_log healthcheck: - test: [ 'CMD', 'pg_isready' ] + test: ["CMD", "pg_isready"] interval: 1s timeout: 3s retries: 30 @@ -1020,7 +1048,7 @@ services: volumes: - ./volumes/pgvecto_rs/data:/var/lib/postgresql/data healthcheck: - test: [ 'CMD', 'pg_isready' ] + test: ["CMD", "pg_isready"] interval: 1s timeout: 3s retries: 30 @@ -1059,7 +1087,11 @@ services: ports: - "${OCEANBASE_VECTOR_PORT:-2881}:2881" healthcheck: - test: [ 'CMD-SHELL', 'obclient -h127.0.0.1 -P2881 -uroot@test -p$${OB_TENANT_PASSWORD} -e "SELECT 1;"' ] + test: + [ + "CMD-SHELL", + 'obclient -h127.0.0.1 -P2881 -uroot@test -p$${OB_TENANT_PASSWORD} -e "SELECT 1;"', + ] interval: 10s retries: 30 start_period: 30s @@ -1095,7 +1127,7 @@ services: - ./volumes/milvus/etcd:/etcd command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd healthcheck: - test: [ 'CMD', 'etcdctl', 'endpoint', 'health' ] + test: ["CMD", "etcdctl", "endpoint", "health"] interval: 30s timeout: 20s retries: 3 @@ -1114,7 +1146,7 @@ services: - ./volumes/milvus/minio:/minio_data command: minio server /minio_data --console-address ":9001" healthcheck: - test: [ 'CMD', 'curl', '-f', 'http://localhost:9000/minio/health/live' ] + test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] interval: 30s timeout: 20s retries: 3 @@ -1126,7 +1158,7 @@ services: image: milvusdb/milvus:v2.5.15 profiles: - milvus - command: [ 'milvus', 'run', 'standalone' ] + command: ["milvus", "run", "standalone"] environment: ETCD_ENDPOINTS: ${ETCD_ENDPOINTS:-etcd:2379} MINIO_ADDRESS: ${MINIO_ADDRESS:-minio:9000} @@ -1134,7 +1166,7 @@ services: volumes: - ./volumes/milvus/milvus:/var/lib/milvus healthcheck: - test: [ 'CMD', 'curl', '-f', 'http://localhost:9091/healthz' ] + test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"] interval: 30s start_period: 90s timeout: 20s @@ -1200,7 +1232,7 @@ services: volumes: - ./volumes/opengauss/data:/var/lib/opengauss/data healthcheck: - test: [ "CMD-SHELL", "netstat -lntp | grep tcp6 > /dev/null 2>&1" ] + test: ["CMD-SHELL", "netstat -lntp | grep tcp6 > /dev/null 2>&1"] interval: 10s timeout: 10s retries: 10 @@ -1253,18 +1285,19 @@ services: node.name: dify-es0 discovery.type: single-node xpack.license.self_generated.type: basic - xpack.security.enabled: 'true' - xpack.security.enrollment.enabled: 'false' - xpack.security.http.ssl.enabled: 'false' + xpack.security.enabled: "true" + xpack.security.enrollment.enabled: "false" + xpack.security.http.ssl.enabled: "false" ports: - ${ELASTICSEARCH_PORT:-9200}:9200 deploy: resources: limits: memory: 2g - entrypoint: [ 'sh', '-c', "sh /docker-entrypoint-mount.sh" ] + entrypoint: ["sh", "-c", "sh /docker-entrypoint-mount.sh"] healthcheck: - test: [ 'CMD', 'curl', '-s', 'http://localhost:9200/_cluster/health?pretty' ] + test: + ["CMD", "curl", "-s", "http://localhost:9200/_cluster/health?pretty"] interval: 30s timeout: 10s retries: 50 @@ -1282,17 +1315,17 @@ services: environment: XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY: d1a66dfd-c4d3-4a0a-8290-2abcb83ab3aa NO_PROXY: localhost,127.0.0.1,elasticsearch,kibana - XPACK_SECURITY_ENABLED: 'true' - XPACK_SECURITY_ENROLLMENT_ENABLED: 'false' - XPACK_SECURITY_HTTP_SSL_ENABLED: 'false' - XPACK_FLEET_ISAIRGAPPED: 'true' + XPACK_SECURITY_ENABLED: "true" + XPACK_SECURITY_ENROLLMENT_ENABLED: "false" + XPACK_SECURITY_HTTP_SSL_ENABLED: "false" + XPACK_FLEET_ISAIRGAPPED: "true" I18N_LOCALE: zh-CN - SERVER_PORT: '5601' + SERVER_PORT: "5601" ELASTICSEARCH_HOSTS: http://elasticsearch:9200 ports: - ${KIBANA_PORT:-5601}:5601 healthcheck: - test: [ 'CMD-SHELL', 'curl -s http://localhost:5601 >/dev/null || exit 1' ] + test: ["CMD-SHELL", "curl -s http://localhost:5601 >/dev/null || exit 1"] interval: 30s timeout: 10s retries: 3 From ff7a0e3170492222954843f6ffa31731d538eb7b Mon Sep 17 00:00:00 2001 From: GuanMu Date: Wed, 3 Sep 2025 22:24:45 +0800 Subject: [PATCH 11/15] fix: improve error logging for vector search operation in MyScale (#25087) --- api/core/rag/datasource/vdb/myscale/myscale_vector.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/core/rag/datasource/vdb/myscale/myscale_vector.py b/api/core/rag/datasource/vdb/myscale/myscale_vector.py index 99f766a88a..d048f3b34e 100644 --- a/api/core/rag/datasource/vdb/myscale/myscale_vector.py +++ b/api/core/rag/datasource/vdb/myscale/myscale_vector.py @@ -152,8 +152,8 @@ class MyScaleVector(BaseVector): ) for r in self._client.query(sql).named_results() ] - except Exception as e: - logger.exception("\033[91m\033[1m%s\033[0m \033[95m%s\033[0m", type(e), str(e)) # noqa:TRY401 + except Exception: + logger.exception("Vector search operation failed") return [] def delete(self) -> None: From db53656a45fdb13447a410b9b4609d991013d89d Mon Sep 17 00:00:00 2001 From: Yongtao Huang Date: Wed, 3 Sep 2025 22:27:41 +0800 Subject: [PATCH 12/15] Fix jsonschema compliance: use number instead of float (#25049) Signed-off-by: Yongtao Huang Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- api/core/mcp/server/streamable_http.py | 2 +- .../core/mcp/server/test_streamable_http.py | 65 ++++++++++++++++++- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/api/core/mcp/server/streamable_http.py b/api/core/mcp/server/streamable_http.py index 5851c6d406..3d51ac2333 100644 --- a/api/core/mcp/server/streamable_http.py +++ b/api/core/mcp/server/streamable_http.py @@ -258,5 +258,5 @@ def convert_input_form_to_parameters( parameters[item.variable]["type"] = "string" parameters[item.variable]["enum"] = item.options elif item.type == VariableEntityType.NUMBER: - parameters[item.variable]["type"] = "float" + parameters[item.variable]["type"] = "number" return parameters, required diff --git a/api/tests/unit_tests/core/mcp/server/test_streamable_http.py b/api/tests/unit_tests/core/mcp/server/test_streamable_http.py index ccc5d42bcf..f1d741602a 100644 --- a/api/tests/unit_tests/core/mcp/server/test_streamable_http.py +++ b/api/tests/unit_tests/core/mcp/server/test_streamable_http.py @@ -1,6 +1,7 @@ import json from unittest.mock import Mock, patch +import jsonschema import pytest from core.app.app_config.entities import VariableEntity, VariableEntityType @@ -434,7 +435,7 @@ class TestUtilityFunctions: assert parameters["category"]["enum"] == ["A", "B", "C"] assert "count" in parameters - assert parameters["count"]["type"] == "float" + assert parameters["count"]["type"] == "number" # FILE type should be skipped - it creates empty dict but gets filtered later # Check that it doesn't have any meaningful content @@ -447,3 +448,65 @@ class TestUtilityFunctions: assert "category" not in required # Note: _get_request_id function has been removed as request_id is now passed as parameter + + def test_convert_input_form_to_parameters_jsonschema_validation_ok(self): + """Current schema uses 'number' for numeric fields; it should be a valid JSON Schema.""" + user_input_form = [ + VariableEntity( + type=VariableEntityType.NUMBER, + variable="count", + description="Count", + label="Count", + required=True, + ), + VariableEntity( + type=VariableEntityType.TEXT_INPUT, + variable="name", + description="User name", + label="Name", + required=False, + ), + ] + + parameters_dict = { + "count": "Enter count", + "name": "Enter your name", + } + + parameters, required = convert_input_form_to_parameters(user_input_form, parameters_dict) + + # Build a complete JSON Schema + schema = { + "type": "object", + "properties": parameters, + "required": required, + } + + # 1) The schema itself must be valid + jsonschema.Draft202012Validator.check_schema(schema) + + # 2) Both float and integer instances should pass validation + jsonschema.validate(instance={"count": 3.14, "name": "alice"}, schema=schema) + jsonschema.validate(instance={"count": 2, "name": "bob"}, schema=schema) + + def test_legacy_float_type_schema_is_invalid(self): + """Legacy/buggy behavior: using 'float' should produce an invalid JSON Schema.""" + # Manually construct a legacy/incorrect schema (simulating old behavior) + bad_schema = { + "type": "object", + "properties": { + "count": { + "type": "float", # Invalid type: JSON Schema does not support 'float' + "description": "Enter count", + } + }, + "required": ["count"], + } + + # The schema itself should raise a SchemaError + with pytest.raises(jsonschema.exceptions.SchemaError): + jsonschema.Draft202012Validator.check_schema(bad_schema) + + # Or validation should also raise SchemaError + with pytest.raises(jsonschema.exceptions.SchemaError): + jsonschema.validate(instance={"count": 1.23}, schema=bad_schema) From aae792a9dd043f1d50a390816302efb61fb4cd3f Mon Sep 17 00:00:00 2001 From: 17hz <0x149527@gmail.com> Date: Wed, 3 Sep 2025 22:28:03 +0800 Subject: [PATCH 13/15] chore: Updated pnpm version to 10.15.1 (#25065) --- web/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/package.json b/web/package.json index e64d548824..c736a37281 100644 --- a/web/package.json +++ b/web/package.json @@ -2,7 +2,7 @@ "name": "dify-web", "version": "1.8.1", "private": true, - "packageManager": "pnpm@10.15.0", + "packageManager": "pnpm@10.15.1", "engines": { "node": ">=v22.11.0" }, From a9c7669c16b02df2617e0477e3e1f4e5552c61ab Mon Sep 17 00:00:00 2001 From: NeatGuyCoding <15627489+NeatGuyCoding@users.noreply.github.com> Date: Wed, 3 Sep 2025 22:29:08 +0800 Subject: [PATCH 14/15] chore: comply to RFC 6750 and improve bearer token split (#24955) --- api/controllers/console/auth/oauth_server.py | 29 +++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/api/controllers/console/auth/oauth_server.py b/api/controllers/console/auth/oauth_server.py index f730cfa3fe..a8ba417847 100644 --- a/api/controllers/console/auth/oauth_server.py +++ b/api/controllers/console/auth/oauth_server.py @@ -2,7 +2,7 @@ from functools import wraps from typing import cast import flask_login -from flask import request +from flask import jsonify, request from flask_restx import Resource, reqparse from werkzeug.exceptions import BadRequest, NotFound @@ -46,23 +46,38 @@ def oauth_server_access_token_required(view): authorization_header = request.headers.get("Authorization") if not authorization_header: - raise BadRequest("Authorization header is required") + response = jsonify({"error": "Authorization header is required"}) + response.status_code = 401 + response.headers["WWW-Authenticate"] = "Bearer" + return response - parts = authorization_header.strip().split(" ") + parts = authorization_header.strip().split(None, 1) if len(parts) != 2: - raise BadRequest("Invalid Authorization header format") + response = jsonify({"error": "Invalid Authorization header format"}) + response.status_code = 401 + response.headers["WWW-Authenticate"] = "Bearer" + return response token_type = parts[0].strip() if token_type.lower() != "bearer": - raise BadRequest("token_type is invalid") + response = jsonify({"error": "token_type is invalid"}) + response.status_code = 401 + response.headers["WWW-Authenticate"] = "Bearer" + return response access_token = parts[1].strip() if not access_token: - raise BadRequest("access_token is required") + response = jsonify({"error": "access_token is required"}) + response.status_code = 401 + response.headers["WWW-Authenticate"] = "Bearer" + return response account = OAuthServerService.validate_oauth_access_token(oauth_provider_app.client_id, access_token) if not account: - raise BadRequest("access_token or client_id is invalid") + response = jsonify({"error": "access_token or client_id is invalid"}) + response.status_code = 401 + response.headers["WWW-Authenticate"] = "Bearer" + return response kwargs["account"] = account From 56afb3fd64401a2ff30832f37104b89e52d4aeaf Mon Sep 17 00:00:00 2001 From: zz_xu <591933870@qq.com> Date: Wed, 3 Sep 2025 22:44:22 +0800 Subject: [PATCH 15/15] db internal server error (#24947) Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> --- api/.env.example | 1 + 1 file changed, 1 insertion(+) diff --git a/api/.env.example b/api/.env.example index e947c5584b..eb88c114e6 100644 --- a/api/.env.example +++ b/api/.env.example @@ -75,6 +75,7 @@ DB_PASSWORD=difyai123456 DB_HOST=localhost DB_PORT=5432 DB_DATABASE=dify +SQLALCHEMY_POOL_PRE_PING=true # Storage configuration # use for store upload files, private keys...