-

+

@@ -180,7 +180,7 @@ docker compose up -d
## Contributing
-对于那些想要贡献代码的人,请参阅我们的[贡献指南](https://github.com/langgenius/dify/blob/main/CONTRIBUTING_CN.md)。
+对于那些想要贡献代码的人,请参阅我们的[贡献指南](https://github.com/langgenius/dify/blob/main/CONTRIBUTING/CONTRIBUTING_CN.md)。
同时,请考虑通过社交媒体、活动和会议来支持 Dify 的分享。
> 我们正在寻找贡献者来帮助将 Dify 翻译成除了中文和英文之外的其他语言。如果您有兴趣帮助,请参阅我们的[i18n README](https://github.com/langgenius/dify/blob/main/web/i18n-config/README.md)获取更多信息,并在我们的[Discord 社区服务器](https://discord.gg/8Tpq4AcN9c)的`global-users`频道中留言。
@@ -196,7 +196,7 @@ docker compose up -d
我们欢迎您为 Dify 做出贡献,以帮助改善 Dify。包括:提交代码、问题、新想法,或分享您基于 Dify 创建的有趣且有用的 AI 应用程序。同时,我们也欢迎您在不同的活动、会议和社交媒体上分享 Dify。
- [GitHub Discussion](https://github.com/langgenius/dify/discussions). 👉:分享您的应用程序并与社区交流。
-- [GitHub Issues](https://github.com/langgenius/dify/issues)。👉:使用 Dify.AI 时遇到的错误和问题,请参阅[贡献指南](CONTRIBUTING.md)。
+- [GitHub Issues](https://github.com/langgenius/dify/issues)。👉:使用 Dify.AI 时遇到的错误和问题,请参阅[贡献指南](../CONTRIBUTING.md)。
- [电子邮件支持](mailto:hello@dify.ai?subject=%5BGitHub%5DQuestions%20About%20Dify)。👉:关于使用 Dify.AI 的问题。
- [Discord](https://discord.gg/FngNHpbcY7)。👉:分享您的应用程序并与社区交流。
- [X(Twitter)](https://twitter.com/dify_ai)。👉:分享您的应用程序并与社区交流。
@@ -208,4 +208,4 @@ docker compose up -d
## License
-本仓库遵循 [Dify Open Source License](LICENSE) 开源协议,该许可证本质上是 Apache 2.0,但有一些额外的限制。
+本仓库遵循 [Dify Open Source License](../LICENSE) 开源协议,该许可证本质上是 Apache 2.0,但有一些额外的限制。
diff --git a/README_DE.md b/README/README_DE.md
similarity index 96%
rename from README_DE.md
rename to README/README_DE.md
index a08fe63d4f..d1a5837ab4 100644
--- a/README_DE.md
+++ b/README/README_DE.md
@@ -1,4 +1,4 @@
-
+
📌 Einführung in Dify Workflow File Upload: Google NotebookLM Podcast nachbilden
@@ -39,7 +39,7 @@
-
+
@@ -173,7 +173,7 @@ Stellen Sie Dify mit einem Klick in AKS bereit, indem Sie [Azure Devops Pipeline
## Contributing
-Falls Sie Code beitragen möchten, lesen Sie bitte unseren [Contribution Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING_DE.md). Gleichzeitig bitten wir Sie, Dify zu unterstützen, indem Sie es in den sozialen Medien teilen und auf Veranstaltungen und Konferenzen präsentieren.
+Falls Sie Code beitragen möchten, lesen Sie bitte unseren [Contribution Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING/CONTRIBUTING_DE.md). Gleichzeitig bitten wir Sie, Dify zu unterstützen, indem Sie es in den sozialen Medien teilen und auf Veranstaltungen und Konferenzen präsentieren.
> Wir suchen Mitwirkende, die dabei helfen, Dify in weitere Sprachen zu übersetzen – außer Mandarin oder Englisch. Wenn Sie Interesse an einer Mitarbeit haben, lesen Sie bitte die [i18n README](https://github.com/langgenius/dify/blob/main/web/i18n-config/README.md) für weitere Informationen und hinterlassen Sie einen Kommentar im `global-users`-Kanal unseres [Discord Community Servers](https://discord.gg/8Tpq4AcN9c).
@@ -200,4 +200,4 @@ Um Ihre Privatsphäre zu schützen, vermeiden Sie es bitte, Sicherheitsprobleme
## Lizenz
-Dieses Repository steht unter der [Dify Open Source License](LICENSE), die im Wesentlichen Apache 2.0 mit einigen zusätzlichen Einschränkungen ist.
+Dieses Repository steht unter der [Dify Open Source License](../LICENSE), die im Wesentlichen Apache 2.0 mit einigen zusätzlichen Einschränkungen ist.
diff --git a/README_ES.md b/README/README_ES.md
similarity index 97%
rename from README_ES.md
rename to README/README_ES.md
index d8fdbf54e6..60f0a06868 100644
--- a/README_ES.md
+++ b/README/README_ES.md
@@ -1,4 +1,4 @@
-
+
Dify Cloud ·
@@ -35,7 +35,7 @@
-
+
@@ -170,7 +170,7 @@ Implementa Dify en AKS con un clic usando [Azure Devops Pipeline Helm Chart by @
## Contribuir
-Para aquellos que deseen contribuir con código, consulten nuestra [Guía de contribución](https://github.com/langgenius/dify/blob/main/CONTRIBUTING_ES.md).
+Para aquellos que deseen contribuir con código, consulten nuestra [Guía de contribución](https://github.com/langgenius/dify/blob/main/CONTRIBUTING/CONTRIBUTING_ES.md).
Al mismo tiempo, considera apoyar a Dify compartiéndolo en redes sociales y en eventos y conferencias.
> Estamos buscando colaboradores para ayudar con la traducción de Dify a idiomas que no sean el mandarín o el inglés. Si estás interesado en ayudar, consulta el [README de i18n](https://github.com/langgenius/dify/blob/main/web/i18n-config/README.md) para obtener más información y déjanos un comentario en el canal `global-users` de nuestro [Servidor de Comunidad en Discord](https://discord.gg/8Tpq4AcN9c).
@@ -198,7 +198,7 @@ Para proteger tu privacidad, evita publicar problemas de seguridad en GitHub. En
## Licencia
-Este repositorio está disponible bajo la [Licencia de Código Abierto de Dify](LICENSE), que es esencialmente Apache 2.0 con algunas restricciones adicionales.
+Este repositorio está disponible bajo la [Licencia de Código Abierto de Dify](../LICENSE), que es esencialmente Apache 2.0 con algunas restricciones adicionales.
## Divulgación de Seguridad
@@ -206,4 +206,4 @@ Para proteger tu privacidad, evita publicar problemas de seguridad en GitHub. En
## Licencia
-Este repositorio está disponible bajo la [Licencia de Código Abierto de Dify](LICENSE), que es esencialmente Apache 2.0 con algunas restricciones adicionales.
+Este repositorio está disponible bajo la [Licencia de Código Abierto de Dify](../LICENSE), que es esencialmente Apache 2.0 con algunas restricciones adicionales.
diff --git a/README_FR.md b/README/README_FR.md
similarity index 97%
rename from README_FR.md
rename to README/README_FR.md
index 7474ea50c2..a782bd16f8 100644
--- a/README_FR.md
+++ b/README/README_FR.md
@@ -1,4 +1,4 @@
-
+
Dify Cloud ·
@@ -35,7 +35,7 @@
-
+
@@ -168,7 +168,7 @@ Déployez Dify sur AKS en un clic en utilisant [Azure Devops Pipeline Helm Chart
## Contribuer
-Pour ceux qui souhaitent contribuer du code, consultez notre [Guide de contribution](https://github.com/langgenius/dify/blob/main/CONTRIBUTING_FR.md).
+Pour ceux qui souhaitent contribuer du code, consultez notre [Guide de contribution](https://github.com/langgenius/dify/blob/main/CONTRIBUTING/CONTRIBUTING_FR.md).
Dans le même temps, veuillez envisager de soutenir Dify en le partageant sur les réseaux sociaux et lors d'événements et de conférences.
> Nous recherchons des contributeurs pour aider à traduire Dify dans des langues autres que le mandarin ou l'anglais. Si vous êtes intéressé à aider, veuillez consulter le [README i18n](https://github.com/langgenius/dify/blob/main/web/i18n-config/README.md) pour plus d'informations, et laissez-nous un commentaire dans le canal `global-users` de notre [Serveur communautaire Discord](https://discord.gg/8Tpq4AcN9c).
@@ -196,7 +196,7 @@ Pour protéger votre vie privée, veuillez éviter de publier des problèmes de
## Licence
-Ce référentiel est disponible sous la [Licence open source Dify](LICENSE), qui est essentiellement l'Apache 2.0 avec quelques restrictions supplémentaires.
+Ce référentiel est disponible sous la [Licence open source Dify](../LICENSE), qui est essentiellement l'Apache 2.0 avec quelques restrictions supplémentaires.
## Divulgation de sécurité
@@ -204,4 +204,4 @@ Pour protéger votre vie privée, veuillez éviter de publier des problèmes de
## Licence
-Ce référentiel est disponible sous la [Licence open source Dify](LICENSE), qui est essentiellement l'Apache 2.0 avec quelques restrictions supplémentaires.
+Ce référentiel est disponible sous la [Licence open source Dify](../LICENSE), qui est essentiellement l'Apache 2.0 avec quelques restrictions supplémentaires.
diff --git a/README_JA.md b/README/README_JA.md
similarity index 97%
rename from README_JA.md
rename to README/README_JA.md
index a782849f6e..23cd0e692b 100644
--- a/README_JA.md
+++ b/README/README_JA.md
@@ -1,4 +1,4 @@
-
+
Dify Cloud ·
@@ -35,7 +35,7 @@
-
+
@@ -169,7 +169,7 @@ docker compose up -d
## 貢献
-コードに貢献したい方は、[Contribution Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING_JA.md)を参照してください。
+コードに貢献したい方は、[Contribution Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING/CONTRIBUTING_JA.md)を参照してください。
同時に、DifyをSNSやイベント、カンファレンスで共有してサポートしていただけると幸いです。
> Difyを英語または中国語以外の言語に翻訳してくれる貢献者を募集しています。興味がある場合は、詳細については[i18n README](https://github.com/langgenius/dify/blob/main/web/i18n-config/README.md)を参照してください。また、[Discordコミュニティサーバー](https://discord.gg/8Tpq4AcN9c)の`global-users`チャンネルにコメントを残してください。
@@ -183,10 +183,10 @@ docker compose up -d
## コミュニティ & お問い合わせ
- [GitHub Discussion](https://github.com/langgenius/dify/discussions). 主に: フィードバックの共有や質問。
-- [GitHub Issues](https://github.com/langgenius/dify/issues). 主に: Dify.AIを使用する際に発生するエラーや問題については、[貢献ガイド](CONTRIBUTING_JA.md)を参照してください
+- [GitHub Issues](https://github.com/langgenius/dify/issues). 主に: Dify.AIを使用する際に発生するエラーや問題については、[貢献ガイド](../CONTRIBUTING/CONTRIBUTING_JA.md)を参照してください
- [Discord](https://discord.gg/FngNHpbcY7). 主に: アプリケーションの共有やコミュニティとの交流。
- [X(Twitter)](https://twitter.com/dify_ai). 主に: アプリケーションの共有やコミュニティとの交流。
## ライセンス
-このリポジトリは、Dify Open Source License にいくつかの追加制限を加えた[Difyオープンソースライセンス](LICENSE)の下で利用可能です。
+このリポジトリは、Dify Open Source License にいくつかの追加制限を加えた[Difyオープンソースライセンス](../LICENSE)の下で利用可能です。
diff --git a/README_KL.md b/README/README_KL.md
similarity index 98%
rename from README_KL.md
rename to README/README_KL.md
index 93da9a6140..cae02f56fe 100644
--- a/README_KL.md
+++ b/README/README_KL.md
@@ -1,4 +1,4 @@
-
+
Dify Cloud ·
@@ -35,7 +35,7 @@
-
+
@@ -199,4 +199,4 @@ To protect your privacy, please avoid posting security issues on GitHub. Instead
## License
-This repository is available under the [Dify Open Source License](LICENSE), which is essentially Apache 2.0 with a few additional restrictions.
+This repository is available under the [Dify Open Source License](../LICENSE), which is essentially Apache 2.0 with a few additional restrictions.
diff --git a/README_KR.md b/README/README_KR.md
similarity index 97%
rename from README_KR.md
rename to README/README_KR.md
index ec28cc0f61..e1a2a82677 100644
--- a/README_KR.md
+++ b/README/README_KR.md
@@ -1,4 +1,4 @@
-
+
Dify 클라우드 ·
@@ -35,7 +35,7 @@
-
+
@@ -162,7 +162,7 @@ Dify를 Kubernetes에 배포하고 프리미엄 스케일링 설정을 구성했
## 기여
-코드에 기여하고 싶은 분들은 [기여 가이드](https://github.com/langgenius/dify/blob/main/CONTRIBUTING_KR.md)를 참조하세요.
+코드에 기여하고 싶은 분들은 [기여 가이드](https://github.com/langgenius/dify/blob/main/CONTRIBUTING/CONTRIBUTING_KR.md)를 참조하세요.
동시에 Dify를 소셜 미디어와 행사 및 컨퍼런스에 공유하여 지원하는 것을 고려해 주시기 바랍니다.
> 우리는 Dify를 중국어나 영어 이외의 언어로 번역하는 데 도움을 줄 수 있는 기여자를 찾고 있습니다. 도움을 주고 싶으시다면 [i18n README](https://github.com/langgenius/dify/blob/main/web/i18n-config/README.md)에서 더 많은 정보를 확인하시고 [Discord 커뮤니티 서버](https://discord.gg/8Tpq4AcN9c)의 `global-users` 채널에 댓글을 남겨주세요.
@@ -190,4 +190,4 @@ Dify를 Kubernetes에 배포하고 프리미엄 스케일링 설정을 구성했
## 라이선스
-이 저장소는 기본적으로 몇 가지 추가 제한 사항이 있는 Apache 2.0인 [Dify 오픈 소스 라이선스](LICENSE)에 따라 사용할 수 있습니다.
+이 저장소는 기본적으로 몇 가지 추가 제한 사항이 있는 Apache 2.0인 [Dify 오픈 소스 라이선스](../LICENSE)에 따라 사용할 수 있습니다.
diff --git a/README_PT.md b/README/README_PT.md
similarity index 97%
rename from README_PT.md
rename to README/README_PT.md
index da8f354a49..91132aade4 100644
--- a/README_PT.md
+++ b/README/README_PT.md
@@ -1,4 +1,4 @@
-
+
📌 Introduzindo o Dify Workflow com Upload de Arquivo: Recrie o Podcast Google NotebookLM
@@ -39,7 +39,7 @@
-
+
@@ -168,7 +168,7 @@ Implante o Dify no AKS com um clique usando [Azure Devops Pipeline Helm Chart by
## Contribuindo
-Para aqueles que desejam contribuir com código, veja nosso [Guia de Contribuição](https://github.com/langgenius/dify/blob/main/CONTRIBUTING_PT.md).
+Para aqueles que desejam contribuir com código, veja nosso [Guia de Contribuição](https://github.com/langgenius/dify/blob/main/CONTRIBUTING/CONTRIBUTING_PT.md).
Ao mesmo tempo, considere apoiar o Dify compartilhando-o nas redes sociais e em eventos e conferências.
> Estamos buscando contribuidores para ajudar na tradução do Dify para idiomas além de Mandarim e Inglês. Se você tiver interesse em ajudar, consulte o [README i18n](https://github.com/langgenius/dify/blob/main/web/i18n-config/README.md) para mais informações e deixe-nos um comentário no canal `global-users` em nosso [Servidor da Comunidade no Discord](https://discord.gg/8Tpq4AcN9c).
@@ -196,4 +196,4 @@ Para proteger sua privacidade, evite postar problemas de segurança no GitHub. E
## Licença
-Este repositório está disponível sob a [Licença de Código Aberto Dify](LICENSE), que é essencialmente Apache 2.0 com algumas restrições adicionais.
+Este repositório está disponível sob a [Licença de Código Aberto Dify](../LICENSE), que é essencialmente Apache 2.0 com algumas restrições adicionais.
diff --git a/README_SI.md b/README/README_SI.md
similarity index 97%
rename from README_SI.md
rename to README/README_SI.md
index c20dc3484f..8cd78c065c 100644
--- a/README_SI.md
+++ b/README/README_SI.md
@@ -1,4 +1,4 @@
-
+
📌 Predstavljamo nalaganje datotek Dify Workflow: znova ustvarite Google NotebookLM Podcast
@@ -36,7 +36,7 @@
-
+
@@ -196,4 +196,4 @@ Zaradi zaščite vaše zasebnosti se izogibajte objavljanju varnostnih vprašanj
## Licenca
-To skladišče je na voljo pod [odprtokodno licenco Dify](LICENSE) , ki je v bistvu Apache 2.0 z nekaj dodatnimi omejitvami.
+To skladišče je na voljo pod [odprtokodno licenco Dify](../LICENSE) , ki je v bistvu Apache 2.0 z nekaj dodatnimi omejitvami.
diff --git a/README_TR.md b/README/README_TR.md
similarity index 97%
rename from README_TR.md
rename to README/README_TR.md
index 21df0d1605..9836c6be61 100644
--- a/README_TR.md
+++ b/README/README_TR.md
@@ -1,4 +1,4 @@
-
+
Dify Bulut ·
@@ -35,7 +35,7 @@
-
+
@@ -161,7 +161,7 @@ Dify'ı bulut platformuna tek tıklamayla dağıtın [terraform](https://www.ter
## Katkıda Bulunma
-Kod katkısında bulunmak isteyenler için [Katkı Kılavuzumuza](https://github.com/langgenius/dify/blob/main/CONTRIBUTING_TR.md) bakabilirsiniz.
+Kod katkısında bulunmak isteyenler için [Katkı Kılavuzumuza](https://github.com/langgenius/dify/blob/main/CONTRIBUTING/CONTRIBUTING_TR.md) bakabilirsiniz.
Aynı zamanda, lütfen Dify'ı sosyal medyada, etkinliklerde ve konferanslarda paylaşarak desteklemeyi düşünün.
> Dify'ı Mandarin veya İngilizce dışındaki dillere çevirmemize yardımcı olacak katkıda bulunanlara ihtiyacımız var. Yardımcı olmakla ilgileniyorsanız, lütfen daha fazla bilgi için [i18n README](https://github.com/langgenius/dify/blob/main/web/i18n-config/README.md) dosyasına bakın ve [Discord Topluluk Sunucumuzdaki](https://discord.gg/8Tpq4AcN9c) `global-users` kanalında bize bir yorum bırakın.
@@ -189,4 +189,4 @@ Gizliliğinizi korumak için, lütfen güvenlik sorunlarını GitHub'da paylaşm
## Lisans
-Bu depo, temel olarak Apache 2.0 lisansı ve birkaç ek kısıtlama içeren [Dify Açık Kaynak Lisansı](LICENSE) altında kullanıma sunulmuştur.
+Bu depo, temel olarak Apache 2.0 lisansı ve birkaç ek kısıtlama içeren [Dify Açık Kaynak Lisansı](../LICENSE) altında kullanıma sunulmuştur.
diff --git a/README_TW.md b/README/README_TW.md
similarity index 97%
rename from README_TW.md
rename to README/README_TW.md
index 18d0724784..b9c0b81246 100644
--- a/README_TW.md
+++ b/README/README_TW.md
@@ -1,4 +1,4 @@
-
+
📌 介紹 Dify 工作流程檔案上傳功能:重現 Google NotebookLM Podcast
@@ -39,7 +39,7 @@
-
+
@@ -173,7 +173,7 @@ Dify 的所有功能都提供相應的 API,因此您可以輕鬆地將 Dify
## 貢獻
-對於想要貢獻程式碼的開發者,請參閱我們的[貢獻指南](https://github.com/langgenius/dify/blob/main/CONTRIBUTING_TW.md)。
+對於想要貢獻程式碼的開發者,請參閱我們的[貢獻指南](https://github.com/langgenius/dify/blob/main/CONTRIBUTING/CONTRIBUTING_TW.md)。
同時,也請考慮透過在社群媒體和各種活動與會議上分享 Dify 來支持我們。
> 我們正在尋找貢獻者協助將 Dify 翻譯成中文和英文以外的語言。如果您有興趣幫忙,請查看 [i18n README](https://github.com/langgenius/dify/blob/main/web/i18n-config/README.md) 獲取更多資訊,並在我們的 [Discord 社群伺服器](https://discord.gg/8Tpq4AcN9c) 的 `global-users` 頻道留言給我們。
@@ -201,4 +201,4 @@ Dify 的所有功能都提供相應的 API,因此您可以輕鬆地將 Dify
## 授權條款
-本代碼庫採用 [Dify 開源授權](LICENSE),這基本上是 Apache 2.0 授權加上一些額外限制條款。
+本代碼庫採用 [Dify 開源授權](../LICENSE),這基本上是 Apache 2.0 授權加上一些額外限制條款。
diff --git a/README_VI.md b/README/README_VI.md
similarity index 97%
rename from README_VI.md
rename to README/README_VI.md
index 6d5305fb75..22d74eb31d 100644
--- a/README_VI.md
+++ b/README/README_VI.md
@@ -1,4 +1,4 @@
-
+
Dify Cloud ·
@@ -35,7 +35,7 @@
-
+
@@ -162,7 +162,7 @@ Triển khai Dify lên AKS chỉ với một cú nhấp chuột bằng [Azure De
## Đóng góp
-Đối với những người muốn đóng góp mã, xem [Hướng dẫn Đóng góp](https://github.com/langgenius/dify/blob/main/CONTRIBUTING_VI.md) của chúng tôi.
+Đối với những người muốn đóng góp mã, xem [Hướng dẫn Đóng góp](https://github.com/langgenius/dify/blob/main/CONTRIBUTING/CONTRIBUTING_VI.md) của chúng tôi.
Đồng thời, vui lòng xem xét hỗ trợ Dify bằng cách chia sẻ nó trên mạng xã hội và tại các sự kiện và hội nghị.
> Chúng tôi đang tìm kiếm người đóng góp để giúp dịch Dify sang các ngôn ngữ khác ngoài tiếng Trung hoặc tiếng Anh. Nếu bạn quan tâm đến việc giúp đỡ, vui lòng xem [README i18n](https://github.com/langgenius/dify/blob/main/web/i18n-config/README.md) để biết thêm thông tin và để lại bình luận cho chúng tôi trong kênh `global-users` của [Máy chủ Cộng đồng Discord](https://discord.gg/8Tpq4AcN9c) của chúng tôi.
@@ -190,4 +190,4 @@ Triển khai Dify lên AKS chỉ với một cú nhấp chuột bằng [Azure De
## Giấy phép
-Kho lưu trữ này có sẵn theo [Giấy phép Mã nguồn Mở Dify](LICENSE), về cơ bản là Apache 2.0 với một vài hạn chế bổ sung.
+Kho lưu trữ này có sẵn theo [Giấy phép Mã nguồn Mở Dify](../LICENSE), về cơ bản là Apache 2.0 với một vài hạn chế bổ sung.
From 0e4f19eee01393da757b583c87f0701c2009b2de Mon Sep 17 00:00:00 2001
From: Timo <57227498+EchterTimo@users.noreply.github.com>
Date: Sat, 27 Sep 2025 15:03:05 +0200
Subject: [PATCH 046/173] Fix ChatClient.audio_to_text files keyword to make it
work (#26317)
Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
---
sdks/python-client/dify_client/client.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sdks/python-client/dify_client/client.py b/sdks/python-client/dify_client/client.py
index 791cb98a1b..201391eae9 100644
--- a/sdks/python-client/dify_client/client.py
+++ b/sdks/python-client/dify_client/client.py
@@ -139,9 +139,9 @@ class ChatClient(DifyClient):
data = {"user": user}
return self._send_request("DELETE", f"/conversations/{conversation_id}", data)
- def audio_to_text(self, audio_file: dict, user: str):
+ def audio_to_text(self, audio_file: IO[bytes] | tuple, user: str):
data = {"user": user}
- files = {"audio_file": audio_file}
+ files = {"file": audio_file}
return self._send_request_with_files("POST", "/audio-to-text", data, files)
From 043ec46c331b4ad82d73916f7a9491ecc8d877fb Mon Sep 17 00:00:00 2001
From: "Junyan Qin (Chin)"
Date: Sun, 28 Sep 2025 10:26:11 +0800
Subject: [PATCH 047/173] perf: distribute concurrent plugin auto upgrade tasks
(#26282)
---
api/schedule/check_upgradable_plugin_task.py | 33 ++++++++++++++------
1 file changed, 24 insertions(+), 9 deletions(-)
diff --git a/api/schedule/check_upgradable_plugin_task.py b/api/schedule/check_upgradable_plugin_task.py
index 08a5cfce79..a9ad27b059 100644
--- a/api/schedule/check_upgradable_plugin_task.py
+++ b/api/schedule/check_upgradable_plugin_task.py
@@ -1,3 +1,4 @@
+import math
import time
import click
@@ -8,6 +9,7 @@ from models.account import TenantPluginAutoUpgradeStrategy
from tasks.process_tenant_plugin_autoupgrade_check_task import process_tenant_plugin_autoupgrade_check_task
AUTO_UPGRADE_MINIMAL_CHECKING_INTERVAL = 15 * 60 # 15 minutes
+MAX_CONCURRENT_CHECK_TASKS = 20
@app.celery.task(queue="plugin")
@@ -30,15 +32,28 @@ def check_upgradable_plugin_task():
.all()
)
- for strategy in strategies:
- process_tenant_plugin_autoupgrade_check_task.delay(
- strategy.tenant_id,
- strategy.strategy_setting,
- strategy.upgrade_time_of_day,
- strategy.upgrade_mode,
- strategy.exclude_plugins,
- strategy.include_plugins,
- )
+ total_strategies = len(strategies)
+ click.echo(click.style(f"Total strategies: {total_strategies}", fg="green"))
+
+ batch_chunk_count = math.ceil(
+ total_strategies / MAX_CONCURRENT_CHECK_TASKS
+ ) # make sure all strategies are checked in this interval
+ batch_interval_time = (AUTO_UPGRADE_MINIMAL_CHECKING_INTERVAL / batch_chunk_count) if batch_chunk_count > 0 else 0
+
+ for i in range(0, total_strategies, MAX_CONCURRENT_CHECK_TASKS):
+ batch_strategies = strategies[i : i + MAX_CONCURRENT_CHECK_TASKS]
+ for strategy in batch_strategies:
+ process_tenant_plugin_autoupgrade_check_task.delay(
+ strategy.tenant_id,
+ strategy.strategy_setting,
+ strategy.upgrade_time_of_day,
+ strategy.upgrade_mode,
+ strategy.exclude_plugins,
+ strategy.include_plugins,
+ )
+
+ if batch_interval_time > 0.0001: # if lower than 1ms, skip
+ time.sleep(batch_interval_time)
end_at = time.perf_counter()
click.echo(
From 244c132656c50bd7e8f88ac049ee8b6499477188 Mon Sep 17 00:00:00 2001
From: goofy <38034027+goofy-z@users.noreply.github.com>
Date: Sun, 28 Sep 2025 10:44:20 +0800
Subject: [PATCH 048/173] fix compatibility problem caused by tool node
attribute 'tool_node_version' judgement error (#26274)
---
api/core/workflow/nodes/agent/agent_node.py | 2 +-
api/core/workflow/nodes/tool/tool_node.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/api/core/workflow/nodes/agent/agent_node.py b/api/core/workflow/nodes/agent/agent_node.py
index ec05805879..a01686a4b8 100644
--- a/api/core/workflow/nodes/agent/agent_node.py
+++ b/api/core/workflow/nodes/agent/agent_node.py
@@ -288,7 +288,7 @@ class AgentNode(Node):
# But for backward compatibility with historical data
# this version field judgment is still preserved here.
runtime_variable_pool: VariablePool | None = None
- if node_data.version != "1" or node_data.tool_node_version != "1":
+ if node_data.version != "1" or node_data.tool_node_version is not None:
runtime_variable_pool = variable_pool
tool_runtime = ToolManager.get_agent_tool_runtime(
self.tenant_id, self.app_id, entity, self.invoke_from, runtime_variable_pool
diff --git a/api/core/workflow/nodes/tool/tool_node.py b/api/core/workflow/nodes/tool/tool_node.py
index 5f2abcd378..ce1a879ff1 100644
--- a/api/core/workflow/nodes/tool/tool_node.py
+++ b/api/core/workflow/nodes/tool/tool_node.py
@@ -79,7 +79,7 @@ class ToolNode(Node):
# But for backward compatibility with historical data
# this version field judgment is still preserved here.
variable_pool: VariablePool | None = None
- if node_data.version != "1" or node_data.tool_node_version != "1":
+ if node_data.version != "1" or node_data.tool_node_version is not None:
variable_pool = self.graph_runtime_state.variable_pool
tool_runtime = ToolManager.get_workflow_tool_runtime(
self.tenant_id, self.app_id, self._node_id, self._node_data, self.invoke_from, variable_pool
From 095c56a646943bb3eeaa6aa091d3dccb1e0b7edb Mon Sep 17 00:00:00 2001
From: -LAN-
Date: Sun, 28 Sep 2025 13:37:06 +0800
Subject: [PATCH 049/173] refactor(router): apply ns.route style (#26339)
---
api/controllers/console/__init__.py | 122 +++---------------
api/controllers/console/app/app_import.py | 5 +
.../console/auth/data_source_bearer_auth.py | 10 +-
.../console/auth/email_register.py | 10 +-
.../console/auth/forgot_password.py | 5 -
api/controllers/console/auth/login.py | 16 +--
api/controllers/console/auth/oauth_server.py | 12 +-
api/controllers/console/billing/billing.py | 8 +-
api/controllers/console/billing/compliance.py | 6 +-
.../console/datasets/data_source.py | 26 ++--
.../console/datasets/datasets_document.py | 27 +---
.../console/datasets/datasets_segments.py | 42 +++---
api/controllers/console/datasets/metadata.py | 14 +-
.../datasets/rag_pipeline/datasource_auth.py | 61 ++-------
.../datasource_content_preview.py | 9 +-
.../datasets/rag_pipeline/rag_pipeline.py | 24 +---
api/controllers/console/explore/audio.py | 10 ++
api/controllers/console/explore/completion.py | 18 +++
.../console/explore/conversation.py | 22 ++++
api/controllers/console/explore/message.py | 18 +++
api/controllers/console/explore/workflow.py | 4 +
api/controllers/console/files.py | 5 +
api/controllers/console/remote_files.py | 4 +
api/controllers/console/spec.py | 7 +-
24 files changed, 182 insertions(+), 303 deletions(-)
diff --git a/api/controllers/console/__init__.py b/api/controllers/console/__init__.py
index ee02ff3937..621f5066e4 100644
--- a/api/controllers/console/__init__.py
+++ b/api/controllers/console/__init__.py
@@ -1,31 +1,10 @@
+from importlib import import_module
+
from flask import Blueprint
from flask_restx import Namespace
from libs.external_api import ExternalApi
-from .app.app_import import AppImportApi, AppImportCheckDependenciesApi, AppImportConfirmApi
-from .explore.audio import ChatAudioApi, ChatTextApi
-from .explore.completion import ChatApi, ChatStopApi, CompletionApi, CompletionStopApi
-from .explore.conversation import (
- ConversationApi,
- ConversationListApi,
- ConversationPinApi,
- ConversationRenameApi,
- ConversationUnPinApi,
-)
-from .explore.message import (
- MessageFeedbackApi,
- MessageListApi,
- MessageMoreLikeThisApi,
- MessageSuggestedQuestionApi,
-)
-from .explore.workflow import (
- InstalledAppWorkflowRunApi,
- InstalledAppWorkflowTaskStopApi,
-)
-from .files import FileApi, FilePreviewApi, FileSupportTypeApi
-from .remote_files import RemoteFileInfoApi, RemoteFileUploadApi
-
bp = Blueprint("console", __name__, url_prefix="/console/api")
api = ExternalApi(
@@ -35,23 +14,23 @@ api = ExternalApi(
description="Console management APIs for app configuration, monitoring, and administration",
)
-# Create namespace
console_ns = Namespace("console", description="Console management API operations", path="/")
-# File
-api.add_resource(FileApi, "/files/upload")
-api.add_resource(FilePreviewApi, "/files//preview")
-api.add_resource(FileSupportTypeApi, "/files/support-type")
+RESOURCE_MODULES = (
+ "controllers.console.app.app_import",
+ "controllers.console.explore.audio",
+ "controllers.console.explore.completion",
+ "controllers.console.explore.conversation",
+ "controllers.console.explore.message",
+ "controllers.console.explore.workflow",
+ "controllers.console.files",
+ "controllers.console.remote_files",
+)
-# Remote files
-api.add_resource(RemoteFileInfoApi, "/remote-files/")
-api.add_resource(RemoteFileUploadApi, "/remote-files/upload")
-
-# Import App
-api.add_resource(AppImportApi, "/apps/imports")
-api.add_resource(AppImportConfirmApi, "/apps/imports//confirm")
-api.add_resource(AppImportCheckDependenciesApi, "/apps/imports//check-dependencies")
+for module_name in RESOURCE_MODULES:
+ import_module(module_name)
+# Ensure resource modules are imported so route decorators are evaluated.
# Import other controllers
from . import (
admin,
@@ -150,77 +129,6 @@ from .workspace import (
workspace,
)
-# Explore Audio
-api.add_resource(ChatAudioApi, "/installed-apps//audio-to-text", endpoint="installed_app_audio")
-api.add_resource(ChatTextApi, "/installed-apps//text-to-audio", endpoint="installed_app_text")
-
-# Explore Completion
-api.add_resource(
- CompletionApi, "/installed-apps//completion-messages", endpoint="installed_app_completion"
-)
-api.add_resource(
- CompletionStopApi,
- "/installed-apps//completion-messages//stop",
- endpoint="installed_app_stop_completion",
-)
-api.add_resource(
- ChatApi, "/installed-apps//chat-messages", endpoint="installed_app_chat_completion"
-)
-api.add_resource(
- ChatStopApi,
- "/installed-apps//chat-messages//stop",
- endpoint="installed_app_stop_chat_completion",
-)
-
-# Explore Conversation
-api.add_resource(
- ConversationRenameApi,
- "/installed-apps//conversations//name",
- endpoint="installed_app_conversation_rename",
-)
-api.add_resource(
- ConversationListApi, "/installed-apps//conversations", endpoint="installed_app_conversations"
-)
-api.add_resource(
- ConversationApi,
- "/installed-apps//conversations/",
- endpoint="installed_app_conversation",
-)
-api.add_resource(
- ConversationPinApi,
- "/installed-apps//conversations//pin",
- endpoint="installed_app_conversation_pin",
-)
-api.add_resource(
- ConversationUnPinApi,
- "/installed-apps//conversations//unpin",
- endpoint="installed_app_conversation_unpin",
-)
-
-
-# Explore Message
-api.add_resource(MessageListApi, "/installed-apps//messages", endpoint="installed_app_messages")
-api.add_resource(
- MessageFeedbackApi,
- "/installed-apps//messages//feedbacks",
- endpoint="installed_app_message_feedback",
-)
-api.add_resource(
- MessageMoreLikeThisApi,
- "/installed-apps//messages//more-like-this",
- endpoint="installed_app_more_like_this",
-)
-api.add_resource(
- MessageSuggestedQuestionApi,
- "/installed-apps//messages//suggested-questions",
- endpoint="installed_app_suggested_question",
-)
-# Explore Workflow
-api.add_resource(InstalledAppWorkflowRunApi, "/installed-apps//workflows/run")
-api.add_resource(
- InstalledAppWorkflowTaskStopApi, "/installed-apps//workflows/tasks//stop"
-)
-
api.add_namespace(console_ns)
__all__ = [
diff --git a/api/controllers/console/app/app_import.py b/api/controllers/console/app/app_import.py
index aee93a8814..c14f597c25 100644
--- a/api/controllers/console/app/app_import.py
+++ b/api/controllers/console/app/app_import.py
@@ -20,7 +20,10 @@ from services.app_dsl_service import AppDslService, ImportStatus
from services.enterprise.enterprise_service import EnterpriseService
from services.feature_service import FeatureService
+from .. import console_ns
+
+@console_ns.route("/apps/imports")
class AppImportApi(Resource):
@setup_required
@login_required
@@ -74,6 +77,7 @@ class AppImportApi(Resource):
return result.model_dump(mode="json"), 200
+@console_ns.route("/apps/imports//confirm")
class AppImportConfirmApi(Resource):
@setup_required
@login_required
@@ -98,6 +102,7 @@ class AppImportConfirmApi(Resource):
return result.model_dump(mode="json"), 200
+@console_ns.route("/apps/imports//check-dependencies")
class AppImportCheckDependenciesApi(Resource):
@setup_required
@login_required
diff --git a/api/controllers/console/auth/data_source_bearer_auth.py b/api/controllers/console/auth/data_source_bearer_auth.py
index 796e6916cc..207303b212 100644
--- a/api/controllers/console/auth/data_source_bearer_auth.py
+++ b/api/controllers/console/auth/data_source_bearer_auth.py
@@ -2,7 +2,7 @@ from flask_login import current_user
from flask_restx import Resource, reqparse
from werkzeug.exceptions import Forbidden
-from controllers.console import api
+from controllers.console import console_ns
from controllers.console.auth.error import ApiKeyAuthFailedError
from libs.login import login_required
from services.auth.api_key_auth_service import ApiKeyAuthService
@@ -10,6 +10,7 @@ from services.auth.api_key_auth_service import ApiKeyAuthService
from ..wraps import account_initialization_required, setup_required
+@console_ns.route("/api-key-auth/data-source")
class ApiKeyAuthDataSource(Resource):
@setup_required
@login_required
@@ -33,6 +34,7 @@ class ApiKeyAuthDataSource(Resource):
return {"sources": []}
+@console_ns.route("/api-key-auth/data-source/binding")
class ApiKeyAuthDataSourceBinding(Resource):
@setup_required
@login_required
@@ -54,6 +56,7 @@ class ApiKeyAuthDataSourceBinding(Resource):
return {"result": "success"}, 200
+@console_ns.route("/api-key-auth/data-source/")
class ApiKeyAuthDataSourceBindingDelete(Resource):
@setup_required
@login_required
@@ -66,8 +69,3 @@ class ApiKeyAuthDataSourceBindingDelete(Resource):
ApiKeyAuthService.delete_provider_auth(current_user.current_tenant_id, binding_id)
return {"result": "success"}, 204
-
-
-api.add_resource(ApiKeyAuthDataSource, "/api-key-auth/data-source")
-api.add_resource(ApiKeyAuthDataSourceBinding, "/api-key-auth/data-source/binding")
-api.add_resource(ApiKeyAuthDataSourceBindingDelete, "/api-key-auth/data-source/")
diff --git a/api/controllers/console/auth/email_register.py b/api/controllers/console/auth/email_register.py
index 91de19a78a..d3613d9183 100644
--- a/api/controllers/console/auth/email_register.py
+++ b/api/controllers/console/auth/email_register.py
@@ -5,7 +5,7 @@ from sqlalchemy.orm import Session
from configs import dify_config
from constants.languages import languages
-from controllers.console import api
+from controllers.console import console_ns
from controllers.console.auth.error import (
EmailAlreadyInUseError,
EmailCodeError,
@@ -25,6 +25,7 @@ from services.billing_service import BillingService
from services.errors.account import AccountNotFoundError, AccountRegisterError
+@console_ns.route("/email-register/send-email")
class EmailRegisterSendEmailApi(Resource):
@setup_required
@email_password_login_enabled
@@ -52,6 +53,7 @@ class EmailRegisterSendEmailApi(Resource):
return {"result": "success", "data": token}
+@console_ns.route("/email-register/validity")
class EmailRegisterCheckApi(Resource):
@setup_required
@email_password_login_enabled
@@ -92,6 +94,7 @@ class EmailRegisterCheckApi(Resource):
return {"is_valid": True, "email": token_data.get("email"), "token": new_token}
+@console_ns.route("/email-register")
class EmailRegisterResetApi(Resource):
@setup_required
@email_password_login_enabled
@@ -148,8 +151,3 @@ class EmailRegisterResetApi(Resource):
raise AccountInFreezeError()
return account
-
-
-api.add_resource(EmailRegisterSendEmailApi, "/email-register/send-email")
-api.add_resource(EmailRegisterCheckApi, "/email-register/validity")
-api.add_resource(EmailRegisterResetApi, "/email-register")
diff --git a/api/controllers/console/auth/forgot_password.py b/api/controllers/console/auth/forgot_password.py
index 36ccb1d562..704bcf8fb8 100644
--- a/api/controllers/console/auth/forgot_password.py
+++ b/api/controllers/console/auth/forgot_password.py
@@ -221,8 +221,3 @@ class ForgotPasswordResetApi(Resource):
TenantService.create_tenant_member(tenant, account, role="owner")
account.current_tenant = tenant
tenant_was_created.send(tenant)
-
-
-api.add_resource(ForgotPasswordSendEmailApi, "/forgot-password")
-api.add_resource(ForgotPasswordCheckApi, "/forgot-password/validity")
-api.add_resource(ForgotPasswordResetApi, "/forgot-password/resets")
diff --git a/api/controllers/console/auth/login.py b/api/controllers/console/auth/login.py
index 3b35ab3c23..ba614aa828 100644
--- a/api/controllers/console/auth/login.py
+++ b/api/controllers/console/auth/login.py
@@ -7,7 +7,7 @@ from flask_restx import Resource, reqparse
import services
from configs import dify_config
from constants.languages import languages
-from controllers.console import api
+from controllers.console import console_ns
from controllers.console.auth.error import (
AuthenticationFailedError,
EmailCodeError,
@@ -34,6 +34,7 @@ from services.errors.workspace import WorkSpaceNotAllowedCreateError, Workspaces
from services.feature_service import FeatureService
+@console_ns.route("/login")
class LoginApi(Resource):
"""Resource for user login."""
@@ -91,6 +92,7 @@ class LoginApi(Resource):
return {"result": "success", "data": token_pair.model_dump()}
+@console_ns.route("/logout")
class LogoutApi(Resource):
@setup_required
def get(self):
@@ -102,6 +104,7 @@ class LogoutApi(Resource):
return {"result": "success"}
+@console_ns.route("/reset-password")
class ResetPasswordSendEmailApi(Resource):
@setup_required
@email_password_login_enabled
@@ -130,6 +133,7 @@ class ResetPasswordSendEmailApi(Resource):
return {"result": "success", "data": token}
+@console_ns.route("/email-code-login")
class EmailCodeLoginSendEmailApi(Resource):
@setup_required
def post(self):
@@ -162,6 +166,7 @@ class EmailCodeLoginSendEmailApi(Resource):
return {"result": "success", "data": token}
+@console_ns.route("/email-code-login/validity")
class EmailCodeLoginApi(Resource):
@setup_required
def post(self):
@@ -218,6 +223,7 @@ class EmailCodeLoginApi(Resource):
return {"result": "success", "data": token_pair.model_dump()}
+@console_ns.route("/refresh-token")
class RefreshTokenApi(Resource):
def post(self):
parser = reqparse.RequestParser()
@@ -229,11 +235,3 @@ class RefreshTokenApi(Resource):
return {"result": "success", "data": new_token_pair.model_dump()}
except Exception as e:
return {"result": "fail", "data": str(e)}, 401
-
-
-api.add_resource(LoginApi, "/login")
-api.add_resource(LogoutApi, "/logout")
-api.add_resource(EmailCodeLoginSendEmailApi, "/email-code-login")
-api.add_resource(EmailCodeLoginApi, "/email-code-login/validity")
-api.add_resource(ResetPasswordSendEmailApi, "/reset-password")
-api.add_resource(RefreshTokenApi, "/refresh-token")
diff --git a/api/controllers/console/auth/oauth_server.py b/api/controllers/console/auth/oauth_server.py
index a54c1443f8..46281860ae 100644
--- a/api/controllers/console/auth/oauth_server.py
+++ b/api/controllers/console/auth/oauth_server.py
@@ -14,7 +14,7 @@ from models.account import Account
from models.model import OAuthProviderApp
from services.oauth_server import OAUTH_ACCESS_TOKEN_EXPIRES_IN, OAuthGrantType, OAuthServerService
-from .. import api
+from .. import console_ns
P = ParamSpec("P")
R = TypeVar("R")
@@ -86,6 +86,7 @@ def oauth_server_access_token_required(view: Callable[Concatenate[T, OAuthProvid
return decorated
+@console_ns.route("/oauth/provider")
class OAuthServerAppApi(Resource):
@setup_required
@oauth_server_client_id_required
@@ -108,6 +109,7 @@ class OAuthServerAppApi(Resource):
)
+@console_ns.route("/oauth/provider/authorize")
class OAuthServerUserAuthorizeApi(Resource):
@setup_required
@login_required
@@ -125,6 +127,7 @@ class OAuthServerUserAuthorizeApi(Resource):
)
+@console_ns.route("/oauth/provider/token")
class OAuthServerUserTokenApi(Resource):
@setup_required
@oauth_server_client_id_required
@@ -180,6 +183,7 @@ class OAuthServerUserTokenApi(Resource):
)
+@console_ns.route("/oauth/provider/account")
class OAuthServerUserAccountApi(Resource):
@setup_required
@oauth_server_client_id_required
@@ -194,9 +198,3 @@ class OAuthServerUserAccountApi(Resource):
"timezone": account.timezone,
}
)
-
-
-api.add_resource(OAuthServerAppApi, "/oauth/provider")
-api.add_resource(OAuthServerUserAuthorizeApi, "/oauth/provider/authorize")
-api.add_resource(OAuthServerUserTokenApi, "/oauth/provider/token")
-api.add_resource(OAuthServerUserAccountApi, "/oauth/provider/account")
diff --git a/api/controllers/console/billing/billing.py b/api/controllers/console/billing/billing.py
index 39fc7dec6b..fa89f45122 100644
--- a/api/controllers/console/billing/billing.py
+++ b/api/controllers/console/billing/billing.py
@@ -1,12 +1,13 @@
from flask_restx import Resource, reqparse
-from controllers.console import api
+from controllers.console import console_ns
from controllers.console.wraps import account_initialization_required, only_edition_cloud, setup_required
from libs.login import current_user, login_required
from models.model import Account
from services.billing_service import BillingService
+@console_ns.route("/billing/subscription")
class Subscription(Resource):
@setup_required
@login_required
@@ -26,6 +27,7 @@ class Subscription(Resource):
)
+@console_ns.route("/billing/invoices")
class Invoices(Resource):
@setup_required
@login_required
@@ -36,7 +38,3 @@ class Invoices(Resource):
BillingService.is_tenant_owner_or_admin(current_user)
assert current_user.current_tenant_id is not None
return BillingService.get_invoices(current_user.email, current_user.current_tenant_id)
-
-
-api.add_resource(Subscription, "/billing/subscription")
-api.add_resource(Invoices, "/billing/invoices")
diff --git a/api/controllers/console/billing/compliance.py b/api/controllers/console/billing/compliance.py
index 4bc073f679..e489b48c82 100644
--- a/api/controllers/console/billing/compliance.py
+++ b/api/controllers/console/billing/compliance.py
@@ -6,10 +6,11 @@ from libs.helper import extract_remote_ip
from libs.login import login_required
from services.billing_service import BillingService
-from .. import api
+from .. import console_ns
from ..wraps import account_initialization_required, only_edition_cloud, setup_required
+@console_ns.route("/compliance/download")
class ComplianceApi(Resource):
@setup_required
@login_required
@@ -30,6 +31,3 @@ class ComplianceApi(Resource):
ip=ip_address,
device_info=device_info,
)
-
-
-api.add_resource(ComplianceApi, "/compliance/download")
diff --git a/api/controllers/console/datasets/data_source.py b/api/controllers/console/datasets/data_source.py
index 3a9530af84..370e0c0d14 100644
--- a/api/controllers/console/datasets/data_source.py
+++ b/api/controllers/console/datasets/data_source.py
@@ -9,7 +9,7 @@ from sqlalchemy import select
from sqlalchemy.orm import Session
from werkzeug.exceptions import NotFound
-from controllers.console import api
+from controllers.console import console_ns
from controllers.console.wraps import account_initialization_required, setup_required
from core.datasource.entities.datasource_entities import DatasourceProviderType, OnlineDocumentPagesMessage
from core.datasource.online_document.online_document_plugin import OnlineDocumentDatasourcePlugin
@@ -27,6 +27,10 @@ from services.datasource_provider_service import DatasourceProviderService
from tasks.document_indexing_sync_task import document_indexing_sync_task
+@console_ns.route(
+ "/data-source/integrates",
+ "/data-source/integrates//",
+)
class DataSourceApi(Resource):
@setup_required
@login_required
@@ -109,6 +113,7 @@ class DataSourceApi(Resource):
return {"result": "success"}, 200
+@console_ns.route("/notion/pre-import/pages")
class DataSourceNotionListApi(Resource):
@setup_required
@login_required
@@ -196,6 +201,10 @@ class DataSourceNotionListApi(Resource):
return {"notion_info": {**workspace_info, "pages": pages}}, 200
+@console_ns.route(
+ "/notion/workspaces//pages///preview",
+ "/datasets/notion-indexing-estimate",
+)
class DataSourceNotionApi(Resource):
@setup_required
@login_required
@@ -269,6 +278,7 @@ class DataSourceNotionApi(Resource):
return response.model_dump(), 200
+@console_ns.route("/datasets//notion/sync")
class DataSourceNotionDatasetSyncApi(Resource):
@setup_required
@login_required
@@ -285,6 +295,7 @@ class DataSourceNotionDatasetSyncApi(Resource):
return {"result": "success"}, 200
+@console_ns.route("/datasets//documents//notion/sync")
class DataSourceNotionDocumentSyncApi(Resource):
@setup_required
@login_required
@@ -301,16 +312,3 @@ class DataSourceNotionDocumentSyncApi(Resource):
raise NotFound("Document not found.")
document_indexing_sync_task.delay(dataset_id_str, document_id_str)
return {"result": "success"}, 200
-
-
-api.add_resource(DataSourceApi, "/data-source/integrates", "/data-source/integrates//")
-api.add_resource(DataSourceNotionListApi, "/notion/pre-import/pages")
-api.add_resource(
- DataSourceNotionApi,
- "/notion/workspaces//pages///preview",
- "/datasets/notion-indexing-estimate",
-)
-api.add_resource(DataSourceNotionDatasetSyncApi, "/datasets//notion/sync")
-api.add_resource(
- DataSourceNotionDocumentSyncApi, "/datasets//documents//notion/sync"
-)
diff --git a/api/controllers/console/datasets/datasets_document.py b/api/controllers/console/datasets/datasets_document.py
index e6f5daa87b..6aaede0fb3 100644
--- a/api/controllers/console/datasets/datasets_document.py
+++ b/api/controllers/console/datasets/datasets_document.py
@@ -1114,6 +1114,7 @@ class WebsiteDocumentSyncApi(DocumentResource):
return {"result": "success"}, 200
+@console_ns.route("/datasets//documents//pipeline-execution-log")
class DocumentPipelineExecutionLogApi(DocumentResource):
@setup_required
@login_required
@@ -1147,29 +1148,3 @@ class DocumentPipelineExecutionLogApi(DocumentResource):
"input_data": log.input_data,
"datasource_node_id": log.datasource_node_id,
}, 200
-
-
-api.add_resource(GetProcessRuleApi, "/datasets/process-rule")
-api.add_resource(DatasetDocumentListApi, "/datasets//documents")
-api.add_resource(DatasetInitApi, "/datasets/init")
-api.add_resource(
- DocumentIndexingEstimateApi, "/datasets//documents//indexing-estimate"
-)
-api.add_resource(DocumentBatchIndexingEstimateApi, "/datasets//batch//indexing-estimate")
-api.add_resource(DocumentBatchIndexingStatusApi, "/datasets//batch//indexing-status")
-api.add_resource(DocumentIndexingStatusApi, "/datasets//documents//indexing-status")
-api.add_resource(DocumentApi, "/datasets//documents/")
-api.add_resource(
- DocumentProcessingApi, "/datasets//documents//processing/"
-)
-api.add_resource(DocumentMetadataApi, "/datasets//documents//metadata")
-api.add_resource(DocumentStatusApi, "/datasets//documents/status//batch")
-api.add_resource(DocumentPauseApi, "/datasets//documents//processing/pause")
-api.add_resource(DocumentRecoverApi, "/datasets//documents//processing/resume")
-api.add_resource(DocumentRetryApi, "/datasets//retry")
-api.add_resource(DocumentRenameApi, "/datasets//documents//rename")
-
-api.add_resource(WebsiteDocumentSyncApi, "/datasets//documents//website-sync")
-api.add_resource(
- DocumentPipelineExecutionLogApi, "/datasets//documents//pipeline-execution-log"
-)
diff --git a/api/controllers/console/datasets/datasets_segments.py b/api/controllers/console/datasets/datasets_segments.py
index 463fd2d7ec..ba552821d2 100644
--- a/api/controllers/console/datasets/datasets_segments.py
+++ b/api/controllers/console/datasets/datasets_segments.py
@@ -7,7 +7,7 @@ from sqlalchemy import select
from werkzeug.exceptions import Forbidden, NotFound
import services
-from controllers.console import api
+from controllers.console import console_ns
from controllers.console.app.error import ProviderNotInitializeError
from controllers.console.datasets.error import (
ChildChunkDeleteIndexError,
@@ -37,6 +37,7 @@ from services.errors.chunk import ChildChunkIndexingError as ChildChunkIndexingS
from tasks.batch_create_segment_to_index_task import batch_create_segment_to_index_task
+@console_ns.route("/datasets//documents//segments")
class DatasetDocumentSegmentListApi(Resource):
@setup_required
@login_required
@@ -139,6 +140,7 @@ class DatasetDocumentSegmentListApi(Resource):
return {"result": "success"}, 204
+@console_ns.route("/datasets//documents//segment/")
class DatasetDocumentSegmentApi(Resource):
@setup_required
@login_required
@@ -193,6 +195,7 @@ class DatasetDocumentSegmentApi(Resource):
return {"result": "success"}, 200
+@console_ns.route("/datasets//documents//segment")
class DatasetDocumentSegmentAddApi(Resource):
@setup_required
@login_required
@@ -244,6 +247,7 @@ class DatasetDocumentSegmentAddApi(Resource):
return {"data": marshal(segment, segment_fields), "doc_form": document.doc_form}, 200
+@console_ns.route("/datasets//documents//segments/")
class DatasetDocumentSegmentUpdateApi(Resource):
@setup_required
@login_required
@@ -345,6 +349,10 @@ class DatasetDocumentSegmentUpdateApi(Resource):
return {"result": "success"}, 204
+@console_ns.route(
+ "/datasets//documents//segments/batch_import",
+ "/datasets/batch_import_status/",
+)
class DatasetDocumentSegmentBatchImportApi(Resource):
@setup_required
@login_required
@@ -393,7 +401,9 @@ class DatasetDocumentSegmentBatchImportApi(Resource):
@setup_required
@login_required
@account_initialization_required
- def get(self, job_id):
+ def get(self, job_id=None, dataset_id=None, document_id=None):
+ if job_id is None:
+ raise NotFound("The job does not exist.")
job_id = str(job_id)
indexing_cache_key = f"segment_batch_import_{job_id}"
cache_result = redis_client.get(indexing_cache_key)
@@ -403,6 +413,7 @@ class DatasetDocumentSegmentBatchImportApi(Resource):
return {"job_id": job_id, "job_status": cache_result.decode()}, 200
+@console_ns.route("/datasets//documents//segments//child_chunks")
class ChildChunkAddApi(Resource):
@setup_required
@login_required
@@ -553,6 +564,9 @@ class ChildChunkAddApi(Resource):
return {"data": marshal(child_chunks, child_chunk_fields)}, 200
+@console_ns.route(
+ "/datasets//documents//segments//child_chunks/"
+)
class ChildChunkUpdateApi(Resource):
@setup_required
@login_required
@@ -666,27 +680,3 @@ class ChildChunkUpdateApi(Resource):
except ChildChunkIndexingServiceError as e:
raise ChildChunkIndexingError(str(e))
return {"data": marshal(child_chunk, child_chunk_fields)}, 200
-
-
-api.add_resource(DatasetDocumentSegmentListApi, "/datasets//documents//segments")
-api.add_resource(
- DatasetDocumentSegmentApi, "/datasets//documents//segment/"
-)
-api.add_resource(DatasetDocumentSegmentAddApi, "/datasets//documents//segment")
-api.add_resource(
- DatasetDocumentSegmentUpdateApi,
- "/datasets//documents//segments/",
-)
-api.add_resource(
- DatasetDocumentSegmentBatchImportApi,
- "/datasets//documents//segments/batch_import",
- "/datasets/batch_import_status/",
-)
-api.add_resource(
- ChildChunkAddApi,
- "/datasets//documents//segments//child_chunks",
-)
-api.add_resource(
- ChildChunkUpdateApi,
- "/datasets//documents//segments//child_chunks/",
-)
diff --git a/api/controllers/console/datasets/metadata.py b/api/controllers/console/datasets/metadata.py
index 21ab5e4fe1..53dc80eaa5 100644
--- a/api/controllers/console/datasets/metadata.py
+++ b/api/controllers/console/datasets/metadata.py
@@ -4,7 +4,7 @@ from flask_login import current_user
from flask_restx import Resource, marshal_with, reqparse
from werkzeug.exceptions import NotFound
-from controllers.console import api
+from controllers.console import console_ns
from controllers.console.wraps import account_initialization_required, enterprise_license_required, setup_required
from fields.dataset_fields import dataset_metadata_fields
from libs.login import login_required
@@ -16,6 +16,7 @@ from services.entities.knowledge_entities.knowledge_entities import (
from services.metadata_service import MetadataService
+@console_ns.route("/datasets//metadata")
class DatasetMetadataCreateApi(Resource):
@setup_required
@login_required
@@ -50,6 +51,7 @@ class DatasetMetadataCreateApi(Resource):
return MetadataService.get_dataset_metadatas(dataset), 200
+@console_ns.route("/datasets//metadata/")
class DatasetMetadataApi(Resource):
@setup_required
@login_required
@@ -87,6 +89,7 @@ class DatasetMetadataApi(Resource):
return {"result": "success"}, 204
+@console_ns.route("/datasets/metadata/built-in")
class DatasetMetadataBuiltInFieldApi(Resource):
@setup_required
@login_required
@@ -97,6 +100,7 @@ class DatasetMetadataBuiltInFieldApi(Resource):
return {"fields": built_in_fields}, 200
+@console_ns.route("/datasets//metadata/built-in/")
class DatasetMetadataBuiltInFieldActionApi(Resource):
@setup_required
@login_required
@@ -116,6 +120,7 @@ class DatasetMetadataBuiltInFieldActionApi(Resource):
return {"result": "success"}, 200
+@console_ns.route("/datasets//documents/metadata")
class DocumentMetadataEditApi(Resource):
@setup_required
@login_required
@@ -136,10 +141,3 @@ class DocumentMetadataEditApi(Resource):
MetadataService.update_documents_metadata(dataset, metadata_args)
return {"result": "success"}, 200
-
-
-api.add_resource(DatasetMetadataCreateApi, "/datasets//metadata")
-api.add_resource(DatasetMetadataApi, "/datasets//metadata/")
-api.add_resource(DatasetMetadataBuiltInFieldApi, "/datasets/metadata/built-in")
-api.add_resource(DatasetMetadataBuiltInFieldActionApi, "/datasets//metadata/built-in/")
-api.add_resource(DocumentMetadataEditApi, "/datasets//documents/metadata")
diff --git a/api/controllers/console/datasets/rag_pipeline/datasource_auth.py b/api/controllers/console/datasets/rag_pipeline/datasource_auth.py
index 1a845cf326..154d9e646b 100644
--- a/api/controllers/console/datasets/rag_pipeline/datasource_auth.py
+++ b/api/controllers/console/datasets/rag_pipeline/datasource_auth.py
@@ -5,7 +5,7 @@ from flask_restx import Resource, reqparse
from werkzeug.exceptions import Forbidden, NotFound
from configs import dify_config
-from controllers.console import api
+from controllers.console import console_ns
from controllers.console.wraps import (
account_initialization_required,
setup_required,
@@ -19,6 +19,7 @@ from services.datasource_provider_service import DatasourceProviderService
from services.plugin.oauth_service import OAuthProxyService
+@console_ns.route("/oauth/plugin//datasource/get-authorization-url")
class DatasourcePluginOAuthAuthorizationUrl(Resource):
@setup_required
@login_required
@@ -68,6 +69,7 @@ class DatasourcePluginOAuthAuthorizationUrl(Resource):
return response
+@console_ns.route("/oauth/plugin//datasource/callback")
class DatasourceOAuthCallback(Resource):
@setup_required
def get(self, provider_id: str):
@@ -123,6 +125,7 @@ class DatasourceOAuthCallback(Resource):
return redirect(f"{dify_config.CONSOLE_WEB_URL}/oauth-callback")
+@console_ns.route("/auth/plugin/datasource/")
class DatasourceAuth(Resource):
@setup_required
@login_required
@@ -165,6 +168,7 @@ class DatasourceAuth(Resource):
return {"result": datasources}, 200
+@console_ns.route("/auth/plugin/datasource//delete")
class DatasourceAuthDeleteApi(Resource):
@setup_required
@login_required
@@ -188,6 +192,7 @@ class DatasourceAuthDeleteApi(Resource):
return {"result": "success"}, 200
+@console_ns.route("/auth/plugin/datasource//update")
class DatasourceAuthUpdateApi(Resource):
@setup_required
@login_required
@@ -213,6 +218,7 @@ class DatasourceAuthUpdateApi(Resource):
return {"result": "success"}, 201
+@console_ns.route("/auth/plugin/datasource/list")
class DatasourceAuthListApi(Resource):
@setup_required
@login_required
@@ -225,6 +231,7 @@ class DatasourceAuthListApi(Resource):
return {"result": jsonable_encoder(datasources)}, 200
+@console_ns.route("/auth/plugin/datasource/default-list")
class DatasourceHardCodeAuthListApi(Resource):
@setup_required
@login_required
@@ -237,6 +244,7 @@ class DatasourceHardCodeAuthListApi(Resource):
return {"result": jsonable_encoder(datasources)}, 200
+@console_ns.route("/auth/plugin/datasource//custom-client")
class DatasourceAuthOauthCustomClient(Resource):
@setup_required
@login_required
@@ -271,6 +279,7 @@ class DatasourceAuthOauthCustomClient(Resource):
return {"result": "success"}, 200
+@console_ns.route("/auth/plugin/datasource//default")
class DatasourceAuthDefaultApi(Resource):
@setup_required
@login_required
@@ -291,6 +300,7 @@ class DatasourceAuthDefaultApi(Resource):
return {"result": "success"}, 200
+@console_ns.route("/auth/plugin/datasource//update-name")
class DatasourceUpdateProviderNameApi(Resource):
@setup_required
@login_required
@@ -311,52 +321,3 @@ class DatasourceUpdateProviderNameApi(Resource):
credential_id=args["credential_id"],
)
return {"result": "success"}, 200
-
-
-api.add_resource(
- DatasourcePluginOAuthAuthorizationUrl,
- "/oauth/plugin//datasource/get-authorization-url",
-)
-api.add_resource(
- DatasourceOAuthCallback,
- "/oauth/plugin//datasource/callback",
-)
-api.add_resource(
- DatasourceAuth,
- "/auth/plugin/datasource/",
-)
-
-api.add_resource(
- DatasourceAuthUpdateApi,
- "/auth/plugin/datasource//update",
-)
-
-api.add_resource(
- DatasourceAuthDeleteApi,
- "/auth/plugin/datasource//delete",
-)
-
-api.add_resource(
- DatasourceAuthListApi,
- "/auth/plugin/datasource/list",
-)
-
-api.add_resource(
- DatasourceHardCodeAuthListApi,
- "/auth/plugin/datasource/default-list",
-)
-
-api.add_resource(
- DatasourceAuthOauthCustomClient,
- "/auth/plugin/datasource//custom-client",
-)
-
-api.add_resource(
- DatasourceAuthDefaultApi,
- "/auth/plugin/datasource//default",
-)
-
-api.add_resource(
- DatasourceUpdateProviderNameApi,
- "/auth/plugin/datasource//update-name",
-)
diff --git a/api/controllers/console/datasets/rag_pipeline/datasource_content_preview.py b/api/controllers/console/datasets/rag_pipeline/datasource_content_preview.py
index 05fa681a33..6c04cc877a 100644
--- a/api/controllers/console/datasets/rag_pipeline/datasource_content_preview.py
+++ b/api/controllers/console/datasets/rag_pipeline/datasource_content_preview.py
@@ -4,7 +4,7 @@ from flask_restx import ( # type: ignore
)
from werkzeug.exceptions import Forbidden
-from controllers.console import api
+from controllers.console import console_ns
from controllers.console.datasets.wraps import get_rag_pipeline
from controllers.console.wraps import account_initialization_required, setup_required
from libs.login import current_user, login_required
@@ -13,6 +13,7 @@ from models.dataset import Pipeline
from services.rag_pipeline.rag_pipeline import RagPipelineService
+@console_ns.route("/rag/pipelines//workflows/published/datasource/nodes//preview")
class DataSourceContentPreviewApi(Resource):
@setup_required
@login_required
@@ -49,9 +50,3 @@ class DataSourceContentPreviewApi(Resource):
credential_id=args.get("credential_id"),
)
return preview_content, 200
-
-
-api.add_resource(
- DataSourceContentPreviewApi,
- "/rag/pipelines/