@nocobase/plugin-ai 2.3.0-alpha.1 → 2.3.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. package/dist/ai/docs/nocobase/ai-dev/watermark-plugin.md +2 -0
  2. package/dist/ai/docs/nocobase/ai-employees/block/ai-chat-box.md +133 -0
  3. package/dist/ai/docs/nocobase/ai-employees/knowledge-base/knowledge-base/documents.md +1 -1
  4. package/dist/ai/docs/nocobase/ai-employees/knowledge-base/knowledge-base/index.md +11 -7
  5. package/dist/ai/docs/nocobase/ai-employees/knowledge-base/knowledge-base/settings.md +12 -8
  6. package/dist/ai/docs/nocobase/ai-employees/knowledge-base/rag.md +43 -13
  7. package/dist/ai/docs/nocobase/ai-employees/knowledge-base/vector-database.md +3 -3
  8. package/dist/ai/docs/nocobase/ai-employees/workflow/nodes/knowledge/create-document.md +1 -1
  9. package/dist/ai/docs/nocobase/api/app/env.md +2 -0
  10. package/dist/ai/docs/nocobase/api/cli/api/resource/create.md +4 -3
  11. package/dist/ai/docs/nocobase/building-tips/ai-fill-js-block-form.md +1092 -0
  12. package/dist/ai/docs/nocobase/data-sources/calendar/calendar-collection.md +100 -3
  13. package/dist/ai/docs/nocobase/data-sources/collection-comment/index.md +92 -39
  14. package/dist/ai/docs/nocobase/data-sources/collection-sql/index.md +150 -29
  15. package/dist/ai/docs/nocobase/data-sources/collection-tree/index.md +93 -5
  16. package/dist/ai/docs/nocobase/data-sources/collection-view/index.md +226 -4
  17. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/advanced/china-region.md +122 -5
  18. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/advanced/collection-select.md +105 -4
  19. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/advanced/json.md +102 -4
  20. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/advanced/nano-id.md +104 -4
  21. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/advanced/snowflake-id.md +108 -4
  22. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/advanced/sort.md +3 -19
  23. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/advanced/uuid.md +104 -4
  24. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/associations/index.md +44 -8
  25. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/basic/color.md +102 -4
  26. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/basic/email.md +104 -4
  27. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/basic/icon.md +102 -4
  28. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/basic/input.md +112 -8
  29. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/basic/integer.md +103 -4
  30. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/basic/number.md +103 -4
  31. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/basic/password.md +102 -4
  32. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/basic/percent.md +104 -5
  33. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/basic/phone.md +104 -4
  34. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/basic/textarea.md +99 -8
  35. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/basic/url.md +103 -4
  36. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/choices/checkbox-group.md +105 -3
  37. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/choices/checkbox.md +102 -4
  38. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/choices/china-region.md +108 -5
  39. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/choices/multiple-select.md +103 -5
  40. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/choices/radio-group.md +106 -4
  41. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/choices/select.md +103 -5
  42. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/datetime/date.md +102 -4
  43. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/datetime/datetime-without-tz.md +103 -5
  44. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/datetime/datetime.md +103 -5
  45. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/datetime/index.md +53 -47
  46. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/datetime/time.md +102 -4
  47. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/datetime/unix-timestamp.md +103 -5
  48. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/geometric/circle.md +102 -4
  49. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/geometric/line.md +103 -5
  50. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/geometric/point.md +102 -4
  51. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/geometric/polygon.md +102 -4
  52. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/index.md +62 -16
  53. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/media/markdown.md +104 -4
  54. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/media/rich-text.md +105 -5
  55. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/system-info/created-at.md +105 -5
  56. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/system-info/created-by.md +103 -5
  57. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/system-info/space.md +100 -6
  58. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/system-info/table-oid.md +102 -4
  59. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/system-info/updated-at.md +104 -5
  60. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/system-info/updated-by.md +104 -6
  61. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection-fields/validation.md +68 -58
  62. package/dist/ai/docs/nocobase/data-sources/data-modeling/collection.md +32 -13
  63. package/dist/ai/docs/nocobase/data-sources/data-modeling/index.md +41 -33
  64. package/dist/ai/docs/nocobase/data-sources/data-source-external-mariadb/index.md +114 -6
  65. package/dist/ai/docs/nocobase/data-sources/data-source-external-mssql/index.md +117 -6
  66. package/dist/ai/docs/nocobase/data-sources/data-source-external-mysql/index.md +103 -6
  67. package/dist/ai/docs/nocobase/data-sources/data-source-external-nocobase/index.md +75 -73
  68. package/dist/ai/docs/nocobase/data-sources/data-source-external-oracle/index.md +129 -11
  69. package/dist/ai/docs/nocobase/data-sources/data-source-external-postgres/index.md +110 -6
  70. package/dist/ai/docs/nocobase/data-sources/data-source-kingbase/index.md +75 -49
  71. package/dist/ai/docs/nocobase/data-sources/data-source-main/general-collection.md +116 -15
  72. package/dist/ai/docs/nocobase/data-sources/data-source-main/index.md +92 -62
  73. package/dist/ai/docs/nocobase/data-sources/data-source-main/inheritance-collection.md +97 -10
  74. package/dist/ai/docs/nocobase/data-sources/data-source-manager/external-database.md +97 -58
  75. package/dist/ai/docs/nocobase/data-sources/data-source-manager/index.md +32 -24
  76. package/dist/ai/docs/nocobase/data-sources/data-source-rest-api/index.md +115 -153
  77. package/dist/ai/docs/nocobase/data-sources/external/clickhouse.md +124 -0
  78. package/dist/ai/docs/nocobase/data-sources/external/doris.md +130 -0
  79. package/dist/ai/docs/nocobase/data-sources/external/index.md +140 -0
  80. package/dist/ai/docs/nocobase/data-sources/external/kingbase.md +129 -0
  81. package/dist/ai/docs/nocobase/data-sources/external/mariadb.md +126 -0
  82. package/dist/ai/docs/nocobase/data-sources/external/mssql.md +129 -0
  83. package/dist/ai/docs/nocobase/data-sources/external/mysql.md +115 -0
  84. package/dist/ai/docs/nocobase/data-sources/external/nocobase.md +159 -0
  85. package/dist/ai/docs/nocobase/data-sources/external/oceanbase.md +126 -0
  86. package/dist/ai/docs/nocobase/data-sources/external/oracle.md +158 -0
  87. package/dist/ai/docs/nocobase/data-sources/external/postgresql.md +122 -0
  88. package/dist/ai/docs/nocobase/data-sources/external/rest-api.md +245 -0
  89. package/dist/ai/docs/nocobase/data-sources/field-attachment-url/index.md +100 -12
  90. package/dist/ai/docs/nocobase/data-sources/field-encryption/index.md +48 -47
  91. package/dist/ai/docs/nocobase/data-sources/field-formula/index.md +99 -5
  92. package/dist/ai/docs/nocobase/data-sources/field-markdown-vditor/index.md +105 -5
  93. package/dist/ai/docs/nocobase/data-sources/field-sequence/index.md +102 -5
  94. package/dist/ai/docs/nocobase/data-sources/field-signature/index.md +18 -16
  95. package/dist/ai/docs/nocobase/data-sources/field-sort/index.md +76 -73
  96. package/dist/ai/docs/nocobase/data-sources/file-manager/field-attachment.md +101 -7
  97. package/dist/ai/docs/nocobase/data-sources/file-manager/file-collection.md +101 -14
  98. package/dist/ai/docs/nocobase/data-sources/index.md +49 -33
  99. package/dist/ai/docs/nocobase/data-sources/main/index.md +130 -0
  100. package/dist/ai/docs/nocobase/data-sources/main/kingbase.md +147 -0
  101. package/dist/ai/docs/nocobase/data-sources/main/mariadb.md +59 -0
  102. package/dist/ai/docs/nocobase/data-sources/main/mysql.md +59 -0
  103. package/dist/ai/docs/nocobase/data-sources/main/oceanbase.md +62 -0
  104. package/dist/ai/docs/nocobase/data-sources/main/postgresql.md +61 -0
  105. package/dist/ai/docs/nocobase/file-manager/file-preview/index.md +44 -3
  106. package/dist/ai/docs/nocobase/file-manager/stable-url.md +1 -1
  107. package/dist/ai/docs/nocobase/file-manager/storage/aliyun-oss.md +100 -3
  108. package/dist/ai/docs/nocobase/file-manager/storage/index.md +76 -26
  109. package/dist/ai/docs/nocobase/file-manager/storage/local.md +4 -2
  110. package/dist/ai/docs/nocobase/file-manager/storage/s3-pro.md +58 -7
  111. package/dist/ai/docs/nocobase/get-started/installation/docker-nginx.mdx +4 -1
  112. package/dist/ai/docs/nocobase/get-started/installation/docker.mdx +2 -0
  113. package/dist/ai/docs/nocobase/get-started/installation/env.md +13 -1
  114. package/dist/ai/docs/nocobase/nocobase-cli/production/reverse-proxy/caddy.md +28 -5
  115. package/dist/ai/docs/nocobase/nocobase-cli/production/reverse-proxy/nginx.md +25 -0
  116. package/dist/ai/docs/nocobase/ops-management/migration-manager/built-in-tables.md +1 -2
  117. package/dist/ai/docs/nocobase/plugin-development/build.md +10 -4
  118. package/dist/ai/docs/nocobase/plugin-development/client/appendix/faq.md +1 -1
  119. package/dist/ai/docs/nocobase/plugin-development/client/examples/custom-action.md +2 -0
  120. package/dist/ai/docs/nocobase/plugin-development/client/examples/custom-block.md +2 -0
  121. package/dist/ai/docs/nocobase/plugin-development/client/examples/custom-field.md +2 -0
  122. package/dist/ai/docs/nocobase/plugin-development/client/examples/fullstack-plugin.md +2 -0
  123. package/dist/ai/docs/nocobase/plugin-development/client/examples/settings-page.md +2 -0
  124. package/dist/ai/docs/nocobase/plugin-development/common/i18n.md +3 -3
  125. package/dist/ai/docs/nocobase/plugin-development/server/cache.md +1 -1
  126. package/dist/ai/docs/nocobase/plugin-development/server/collections.md +0 -6
  127. package/dist/ai/docs/nocobase/plugin-development/server/command.md +2 -2
  128. package/dist/ai/docs/nocobase/plugin-development/server/context.md +2 -2
  129. package/dist/ai/docs/nocobase/plugin-development/server/i18n.md +4 -4
  130. package/dist/ai/docs/nocobase/plugin-development/write-your-first-plugin.md +91 -43
  131. package/dist/ai/docs/nocobase/runjs/context/ai.md +194 -4
  132. package/dist/ai/docs/nocobase/security/guide.md +17 -2
  133. package/dist/ai/docs/nocobase/users-permissions/sync/index.md +8 -1
  134. package/dist/ai/docs/nocobase/users-permissions/sync/sources/dingtalk.md +138 -0
  135. package/dist/ai/docs/nocobase/users-permissions/sync/sources/ldap.md +87 -0
  136. package/dist/ai/docs/nocobase/workflow/nodes/javascript.md +21 -1
  137. package/dist/ai/tools/executeFrontendTool.d.ts +10 -0
  138. package/dist/ai/tools/executeFrontendTool.js +86 -0
  139. package/dist/ai/tools/getSkill.js +1 -1
  140. package/dist/ai/tools/knowledge-base-retrieve.js +3 -1
  141. package/dist/ai/tools/loadFrontendTool.d.ts +10 -0
  142. package/dist/ai/tools/loadFrontendTool.js +99 -0
  143. package/dist/client/244.aeb24ce76c510b34.js +10 -0
  144. package/dist/client/{525.203778500aca5d05.js → 525.94dd4136c1361477.js} +1 -1
  145. package/dist/client/681.6ffbc9329b9ac242.js +10 -0
  146. package/dist/client/705.1d735e63c25f66a8.js +10 -0
  147. package/dist/client/index.d.ts +1 -3
  148. package/dist/client/index.js +8 -8
  149. package/dist/client-v2/244.ee9ec45eac0eb99f.js +10 -0
  150. package/dist/client-v2/420.a5b929a5e7f330be.js +10 -0
  151. package/dist/client-v2/681.6890caa389564ff7.js +10 -0
  152. package/dist/client-v2/705.00c101bef403fb44.js +10 -0
  153. package/dist/client-v2/ai-employees/AIEmployeeShortcut.d.ts +2 -0
  154. package/dist/client-v2/ai-employees/AddContextButton.d.ts +2 -0
  155. package/dist/client-v2/ai-employees/chatbox/components/AIEmployeeSwitcher.d.ts +1 -0
  156. package/dist/client-v2/ai-employees/chatbox/components/ChatBoxUnreadBadge.d.ts +17 -0
  157. package/dist/client-v2/ai-employees/chatbox/components/Conversations.d.ts +9 -1
  158. package/dist/client-v2/ai-employees/chatbox/components/MessageRenderers.d.ts +1 -1
  159. package/dist/client-v2/ai-employees/chatbox/components/Messages.d.ts +5 -1
  160. package/dist/client-v2/ai-employees/chatbox/components/ModelSwitcher.d.ts +4 -0
  161. package/dist/client-v2/ai-employees/chatbox/components/Sender.d.ts +33 -1
  162. package/dist/client-v2/ai-employees/chatbox/components/index.d.ts +1 -0
  163. package/dist/client-v2/ai-employees/chatbox/hooks/reasoning-stream.d.ts +10 -0
  164. package/dist/client-v2/ai-employees/chatbox/hooks/useChat.d.ts +8 -5
  165. package/dist/client-v2/ai-employees/chatbox/hooks/useChatBoxActions.d.ts +3 -2
  166. package/dist/client-v2/ai-employees/chatbox/hooks/useChatBoxEffect.d.ts +2 -1
  167. package/dist/client-v2/ai-employees/chatbox/hooks/useChatConversationActions.d.ts +3 -2
  168. package/dist/client-v2/ai-employees/chatbox/hooks/useChatMessageActions.d.ts +4 -2
  169. package/dist/client-v2/ai-employees/chatbox/hooks/useToolCallActions.d.ts +3 -1
  170. package/dist/client-v2/ai-employees/chatbox/hooks/useUploadFiles.d.ts +13 -3
  171. package/dist/client-v2/ai-employees/chatbox/hooks/useWorkflowTasks.d.ts +3 -2
  172. package/dist/client-v2/ai-employees/chatbox/index.d.ts +17 -0
  173. package/dist/client-v2/ai-employees/chatbox/roles.d.ts +2 -153
  174. package/dist/client-v2/ai-employees/chatbox/stores/chat-box.d.ts +46 -33
  175. package/dist/client-v2/ai-employees/chatbox/stores/chat-conversations.d.ts +7 -7
  176. package/dist/client-v2/ai-employees/chatbox/stores/chat-messages.d.ts +23 -18
  177. package/dist/client-v2/ai-employees/chatbox/stores/chat-sender.d.ts +43 -0
  178. package/dist/client-v2/ai-employees/chatbox/stores/chat-tool-call.d.ts +6 -5
  179. package/dist/client-v2/ai-employees/chatbox/stores/chat-tools.d.ts +11 -5
  180. package/dist/client-v2/ai-employees/chatbox/stores/mounted-chat-boxes.d.ts +20 -0
  181. package/dist/client-v2/ai-employees/chatbox/stores/runtime.d.ts +43 -0
  182. package/dist/client-v2/ai-employees/chatbox/stores/workflow-tasks.d.ts +22 -10
  183. package/dist/client-v2/ai-employees/chatbox/upload.d.ts +19 -0
  184. package/dist/client-v2/ai-employees/chatbox/utils.d.ts +28 -4
  185. package/dist/client-v2/ai-employees/frontend-tools.d.ts +11 -0
  186. package/dist/client-v2/ai-employees/tools/SuggestionsOptionsCard.d.ts +1 -1
  187. package/dist/client-v2/ai-employees/tools/WorkflowTaskOutputCard.d.ts +1 -1
  188. package/dist/client-v2/ai-employees/types.d.ts +30 -0
  189. package/dist/client-v2/block/ai-chat-box/AIChatBoxBlockModel.d.ts +21 -0
  190. package/dist/client-v2/block/ai-chat-box/AIChatBoxCoreModel.d.ts +13 -0
  191. package/dist/client-v2/{ai-employees/chatbox/components/DebugPanel.d.ts → block/ai-chat-box/components/AIChatBoxCoreView.d.ts} +1 -1
  192. package/dist/client-v2/block/ai-chat-box/components/AIChatBoxView.d.ts +12 -0
  193. package/dist/client-v2/block/ai-chat-box/index.d.ts +14 -0
  194. package/dist/client-v2/block/ai-chat-box/settings.d.ts +12 -0
  195. package/dist/client-v2/block/ai-chat-box/sub-models.d.ts +26 -0
  196. package/dist/client-v2/block/ai-chat-box/types.d.ts +38 -0
  197. package/dist/client-v2/block/ai-chat-box/utils.d.ts +26 -0
  198. package/dist/client-v2/index.d.ts +3 -5
  199. package/dist/client-v2/index.js +3 -3
  200. package/dist/client-v2/llm-providers/forms.d.ts +2 -0
  201. package/dist/client-v2/llm-providers/index.d.ts +1 -0
  202. package/dist/client-v2/llm-services/model-select.d.ts +33 -0
  203. package/dist/client-v2/llm-services/utils.d.ts +1 -0
  204. package/dist/client-v2/manager/ai-manager.d.ts +10 -3
  205. package/dist/client-v2/manager/frontend-tool-registry.d.ts +30 -0
  206. package/dist/client-v2/models/ai-employees/AIEmployeeActionModel.d.ts +4 -1
  207. package/dist/client-v2/models/ai-employees/AIEmployeeShortcutModel.d.ts +8 -0
  208. package/dist/client-v2/pages/EmployeesPage.d.ts +12 -0
  209. package/dist/client-v2/pages/LLMServicesPage.d.ts +9 -4
  210. package/dist/client-v2/repositories/AIConfigRepository.d.ts +2 -0
  211. package/dist/client-v2/runjs/registerAIEmployeeRunJSFacade.d.ts +1 -0
  212. package/dist/client-v2/workflow/types.d.ts +1 -0
  213. package/dist/collections/ai-employees.d.ts +1 -0
  214. package/dist/collections/ai-employees.js +1 -0
  215. package/dist/common/ai-employee-validation.d.ts +17 -0
  216. package/dist/common/ai-employee-validation.js +67 -0
  217. package/dist/common/error-codes.d.ts +14 -0
  218. package/dist/common/error-codes.js +51 -0
  219. package/dist/common/frontend-tools.d.ts +26 -0
  220. package/dist/common/frontend-tools.js +57 -0
  221. package/dist/common/llm-service-models.d.ts +16 -0
  222. package/dist/common/llm-service-models.js +84 -0
  223. package/dist/externalVersion.js +19 -17
  224. package/dist/locale/de-DE.json +2 -1
  225. package/dist/locale/en-US.json +87 -5
  226. package/dist/locale/es-ES.json +2 -1
  227. package/dist/locale/fr-FR.json +2 -1
  228. package/dist/locale/hu-HU.json +2 -1
  229. package/dist/locale/id-ID.json +2 -1
  230. package/dist/locale/it-IT.json +2 -1
  231. package/dist/locale/ja-JP.json +2 -1
  232. package/dist/locale/ko-KR.json +2 -1
  233. package/dist/locale/nl-NL.json +2 -1
  234. package/dist/locale/pt-BR.json +2 -1
  235. package/dist/locale/ru-RU.json +2 -1
  236. package/dist/locale/tr-TR.json +2 -1
  237. package/dist/locale/uk-UA.json +2 -1
  238. package/dist/locale/vi-VN.json +2 -1
  239. package/dist/locale/zh-CN.json +87 -5
  240. package/dist/locale/zh-TW.json +2 -1
  241. package/dist/node_modules/@langchain/mistralai/package.json +1 -1
  242. package/dist/node_modules/@langchain/xai/package.json +1 -1
  243. package/dist/node_modules/fs-extra/package.json +1 -1
  244. package/dist/node_modules/jsonrepair/package.json +1 -1
  245. package/dist/node_modules/just-bash/package.json +1 -1
  246. package/dist/node_modules/nodejs-snowflake/package.json +1 -1
  247. package/dist/node_modules/openai/package.json +1 -1
  248. package/dist/node_modules/zod/package.json +1 -1
  249. package/dist/server/ai-employees/ai-conversations.d.ts +4 -1
  250. package/dist/server/ai-employees/ai-conversations.js +2 -0
  251. package/dist/server/ai-employees/ai-employee.d.ts +32 -2
  252. package/dist/server/ai-employees/ai-employee.js +367 -79
  253. package/dist/server/ai-employees/ai-knowledge-base.d.ts +21 -1
  254. package/dist/server/ai-employees/ai-knowledge-base.js +87 -12
  255. package/dist/server/ai-employees/middleware/conversation.js +28 -22
  256. package/dist/server/ai-employees/middleware/index.d.ts +1 -0
  257. package/dist/server/ai-employees/middleware/index.js +2 -0
  258. package/dist/server/ai-employees/middleware/tool-result-integrity.d.ts +22 -0
  259. package/dist/server/ai-employees/middleware/tool-result-integrity.js +211 -0
  260. package/dist/server/ai-employees/reasoning-stream-state.d.ts +23 -0
  261. package/dist/server/ai-employees/reasoning-stream-state.js +63 -0
  262. package/dist/server/collections/ai-conversations.js +5 -0
  263. package/dist/server/document-loader/constants.js +1 -1
  264. package/dist/server/features/knowledge-base.d.ts +2 -0
  265. package/dist/server/frontend-tools.d.ts +25 -0
  266. package/dist/server/frontend-tools.js +171 -0
  267. package/dist/server/llm-providers/common/reasoning.js +18 -10
  268. package/dist/server/llm-providers/deepseek/index.d.ts +10 -0
  269. package/dist/server/llm-providers/deepseek/index.js +32 -0
  270. package/dist/server/llm-providers/deepseek/provider.d.ts +57 -0
  271. package/dist/server/llm-providers/deepseek/provider.js +320 -0
  272. package/dist/server/llm-providers/deepseek/reasoning.d.ts +83 -0
  273. package/dist/server/llm-providers/deepseek/reasoning.js +285 -0
  274. package/dist/server/llm-providers/mistral.d.ts +1 -1
  275. package/dist/server/llm-providers/provider.d.ts +1 -0
  276. package/dist/server/llm-providers/provider.js +3 -0
  277. package/dist/server/llm-providers/shengsuanyun.d.ts +29 -0
  278. package/dist/server/llm-providers/shengsuanyun.js +114 -0
  279. package/dist/server/manager/ai-feature-manager.js +1 -1
  280. package/dist/server/manager/ai-manager.d.ts +3 -0
  281. package/dist/server/manager/ai-manager.js +7 -2
  282. package/dist/server/manager/work-context-handler.js +10 -3
  283. package/dist/server/migrations/20260501000000-ai-employee-knowledge-base-retrieval-strategy.d.ts +14 -0
  284. package/dist/server/migrations/20260501000000-ai-employee-knowledge-base-retrieval-strategy.js +49 -0
  285. package/dist/server/plugin.d.ts +1 -0
  286. package/dist/server/plugin.js +31 -0
  287. package/dist/server/resource/aiConversations.d.ts +2 -0
  288. package/dist/server/resource/aiConversations.js +33 -3
  289. package/dist/server/resource/aiEmployees.d.ts +2 -0
  290. package/dist/server/resource/aiEmployees.js +96 -0
  291. package/dist/server/resource/aiWorkflowTasks.js +9 -1
  292. package/dist/server/resource/llmServices.d.ts +11 -0
  293. package/dist/server/resource/llmServices.js +85 -0
  294. package/dist/server/types/ai-message.type.d.ts +4 -0
  295. package/dist/server/types/knowledge-base.type.d.ts +8 -3
  296. package/dist/server/workflow/nodes/employee/files.d.ts +1 -1
  297. package/dist/server/workflow/nodes/employee/files.js +48 -1
  298. package/dist/server/workflow/nodes/employee/index.js +7 -2
  299. package/dist/server/workflow/nodes/employee/types.d.ts +1 -0
  300. package/dist/swagger/common.d.ts +143 -0
  301. package/dist/swagger/common.js +144 -0
  302. package/dist/swagger/employees.d.ts +301 -0
  303. package/dist/swagger/employees.js +131 -0
  304. package/dist/swagger/index.d.ts +1617 -0
  305. package/dist/swagger/index.js +62 -0
  306. package/dist/swagger/llm.d.ts +563 -0
  307. package/dist/swagger/llm.js +255 -0
  308. package/dist/swagger/schemas.d.ts +757 -0
  309. package/dist/swagger/schemas.js +392 -0
  310. package/package.json +2 -2
  311. package/dist/ai/docs/nocobase/ai-employees/knowledge-base/vector-store.md +0 -24
  312. package/dist/ai/docs/nocobase/data-sources/development/index.md +0 -6
  313. package/dist/client/372.40eb52905e3f3049.js +0 -10
  314. package/dist/client/681.399948c18d753667.js +0 -10
  315. package/dist/client/705.380279da896021fb.js +0 -10
  316. package/dist/client-v2/372.8cc3fde09c9bec77.js +0 -10
  317. package/dist/client-v2/406.341be51205c674e0.js +0 -10
  318. package/dist/client-v2/681.082f4f1c7b841983.js +0 -10
  319. package/dist/client-v2/705.1d10027ff8cfdf79.js +0 -10
  320. package/dist/client-v2/ai-employees/chatbox/stores/create-selectors.d.ts +0 -46
  321. package/dist/client-v2/ai-employees/chatbox/utils/normalizeTriggerTaskOptions.d.ts +0 -19
  322. package/dist/client-v2/debug-logger.d.ts +0 -52
  323. package/dist/server/llm-providers/deepseek.d.ts +0 -40
  324. package/dist/server/llm-providers/deepseek.js +0 -174
@@ -28,50 +28,83 @@ yarn pm create @my-project/plugin-hello
28
28
  After the command runs successfully, it will generate basic files in the `packages/plugins/@my-project/plugin-hello` directory. The default structure is as follows:
29
29
 
30
30
  ```bash
31
- ├─ /packages/plugins/@my-project/plugin-hello
32
- ├─ package.json
33
- ├─ README.md
34
- ├─ client-v2.d.ts
35
- ├─ client-v2.js
36
- ├─ server.d.ts
37
- ├─ server.js
38
- └─ src
39
- ├─ index.ts # Default export server-side plugin
40
- ├─ client-v2 # Client-side code location
41
- │ ├─ index.tsx # Default exported client-side plugin class
42
- ├─ plugin.tsx # Plugin entry (extends @nocobase/client-v2 Plugin)
43
- ├─ models # Optional: frontend models (such as flow nodes)
44
- │ └─ index.ts
45
- └─ utils
46
- ├─ index.ts
47
- │ └─ useT.ts
48
- ├─ server # Server-side code location
49
- │ ├─ index.ts # Default exported server-side plugin class
50
- │ ├─ plugin.ts # Plugin entry (extends @nocobase/server Plugin)
51
- │ ├─ collections # Optional: server-side collections
52
- ├─ migrations # Optional: data migrations
53
- │ └─ utils
54
- │ └─ index.ts
55
- ├─ utils
56
- │ ├─ index.ts
57
- │ └─ tExpr.ts
58
- └─ locale # Optional: multi-language
59
- ├─ en-US.json
60
- └─ zh-CN.json
31
+ packages/plugins/@my-project/plugin-hello/
32
+ ├─ package.json
33
+ ├─ README.md
34
+ ├─ .npmignore
35
+ ├─ client-v2.d.ts # v2 client entry type declaration
36
+ ├─ client-v2.js # v2 client entry
37
+ ├─ client.d.ts # v1 client entry type declaration
38
+ ├─ client.js # v1 client entry
39
+ ├─ server.d.ts # Server entry type declaration
40
+ ├─ server.js # Server entry
41
+ └─ src
42
+ ├─ index.ts # Default export server-side plugin
43
+ ├─ client-v2 # v2 client-side code location
44
+ ├─ index.tsx # Default exported client-side plugin class
45
+ ├─ plugin.tsx # Plugin entry (extends @nocobase/client-v2 Plugin)
46
+ └─ client.d.ts
47
+ ├─ client # v1 client-side code location
48
+ ├─ index.tsx
49
+ │ ├─ plugin.tsx
50
+ │ ├─ locale.ts
51
+ │ ├─ models
52
+ │ └─ index.ts
53
+ │ └─ client.d.ts
54
+ ├─ server # Server-side code location
55
+ ├─ index.ts # Default exported server-side plugin class
56
+ │ ├─ plugin.ts # Plugin entry (extends @nocobase/server Plugin)
57
+ │ └─ collections # Server-side collections (empty directory initially)
58
+ └─ locale # Locale resources
59
+ ├─ en-US.json
60
+ └─ zh-CN.json
61
61
  ```
62
62
 
63
- After creation, you can access the plugin manager page in your browser (default URL: http://localhost:13000/admin/settings/plugin-manager) to confirm whether the plugin appears in the list.
63
+ The scaffold generates a minimal skeleton `src/client-v2/` contains only entry files. The `models/` directory and `locale.ts` used in the following steps are ones you create yourself.
64
+
65
+ Next, start development mode so your code changes hot-reload:
66
+
67
+ - If the project was created with the NocoBase CLI (`nb init`), run this from the project root (`<app-path>`):
68
+
69
+ ```bash
70
+ nb source dev
71
+ ```
72
+
73
+ - If you cloned the NocoBase source repository yourself, run this from the source root:
74
+
75
+ ```bash
76
+ yarn dev
77
+ ```
78
+
79
+ Once it is running, access the plugin manager page in your browser (default URL: http://localhost:13000/admin/settings/plugin-manager) to confirm whether the plugin appears in the list.
64
80
 
65
81
  ## Step 2: Implement a Simple Client Block
66
82
 
67
83
  Next, we'll add a custom block model to the plugin to display a welcome message.
68
84
 
69
- 1. **Create a new block model file** `client-v2/models/HelloBlockModel.tsx`:
85
+ 1. **Create the translation helper file** `src/client-v2/locale.ts`. `tExpr` declares a namespaced translation expression, and `useT` provides the translation function inside components:
86
+
87
+ ```ts
88
+ import { tExpr as _tExpr, useFlowEngine } from '@nocobase/flow-engine';
89
+ // @ts-ignore
90
+ import pkg from '../../package.json';
91
+
92
+ export function useT() {
93
+ const engine = useFlowEngine();
94
+ return (str: string) => engine.context.t(str, { ns: [pkg.name, 'client'] });
95
+ }
96
+
97
+ export function tExpr(key: string) {
98
+ return _tExpr(key, { ns: [pkg.name, 'client'] });
99
+ }
100
+ ```
101
+
102
+ 2. **Create a new block model file** `src/client-v2/models/HelloBlockModel.tsx`:
70
103
 
71
104
  ```tsx pure
72
- import { BlockModel } from '@nocobase/client-v2';
73
105
  import React from 'react';
74
- import { tExpr } from '../utils';
106
+ import { BlockModel } from '@nocobase/client-v2';
107
+ import { tExpr } from '../locale';
75
108
 
76
109
  export class HelloBlockModel extends BlockModel {
77
110
  renderComponent() {
@@ -89,18 +122,27 @@ HelloBlockModel.define({
89
122
  });
90
123
  ```
91
124
 
92
- 2. **Register the block model**. Edit `client-v2/models/index.ts` to export the new model for frontend runtime loading:
125
+ 3. **Register the block model**. Creating the model file is not enough on its own — the frontend runtime does not scan the `models/` directory automatically, so you have to register it explicitly in the plugin entry. Edit `src/client-v2/plugin.tsx` and declare how the model is loaded via `registerModelLoaders` inside `load()`:
93
126
 
94
- ```ts
95
- import { ModelConstructor } from '@nocobase/flow-engine';
96
- import { HelloBlockModel } from './HelloBlockModel';
127
+ ```tsx pure
128
+ import { Plugin } from '@nocobase/client-v2';
129
+
130
+ export class PluginHelloClientV2 extends Plugin {
131
+ async load() {
132
+ this.flowEngine.registerModelLoaders({
133
+ HelloBlockModel: {
134
+ loader: () => import('./models/HelloBlockModel'),
135
+ },
136
+ });
137
+ }
138
+ }
97
139
 
98
- export default {
99
- HelloBlockModel,
100
- } as Record<string, ModelConstructor>;
140
+ export default PluginHelloClientV2;
101
141
  ```
102
142
 
103
- After saving the code, if you're running a development script, you should see hot-reload logs in the terminal output.
143
+ `registerModelLoaders` takes lazy-loading functions, so a model is only loaded once it is actually used. The key (`HelloBlockModel`) must match the model class name — the runtime uses it to pick the model class out of the module's named exports.
144
+
145
+ After saving the code, if you're running development mode, you should see hot-reload logs in the terminal output.
104
146
 
105
147
  ## Step 3: Activate and Test the Plugin
106
148
 
@@ -162,7 +204,7 @@ If the plugin is created in a source code repository, the first build will trigg
162
204
 
163
205
  :::
164
206
 
165
- After the build completes, the package file is located at `storage/tar/@my-project/plugin-hello.tar.gz` by default.
207
+ After the build completes, the package file is located under `storage/tar/` by default, named `<package-name>-<version>.tgz` — for example, `storage/tar/@my-project/plugin-hello-0.1.0.tgz`.
166
208
 
167
209
  :::tip
168
210
 
@@ -174,6 +216,12 @@ It's recommended to write test cases to verify core logic before publishing a pl
174
216
 
175
217
  Upload and extract the package file to the target application's `./storage/plugins` directory. For detailed steps, see [Install and Upgrade Plugins](../get-started/install-upgrade-plugins.mdx).
176
218
 
219
+ If the target application was created with the NocoBase CLI (`nb init`), you can also import it directly with `nb plugin import` instead of extracting it manually:
220
+
221
+ ```bash
222
+ nb plugin import /your/path/plugin-hello-0.1.0.tgz
223
+ ```
224
+
177
225
  ## Related Links
178
226
 
179
227
  - [Plugin Development Overview](./index.md) — Understand NocoBase microkernel architecture and plugin lifecycle
@@ -1,23 +1,51 @@
1
1
  ---
2
2
  title: "ctx.ai"
3
- description: "Use ctx.ai in RunJS to trigger AI employee tasks, either with inline task content or with tasks configured on an AI employee action."
4
- keywords: "ctx.ai,AI employee,triggerTask,triggerModelTask,RunJS,NocoBase"
3
+ description: "Use ctx.ai in RunJS to trigger AI employee tasks in the global conversation or a specified AI Chat Box, either with inline task content or with tasks configured on an AI employee action."
4
+ keywords: "ctx.ai,AI employee,uploadFile,attachments,triggerTask,triggerModelTask,onResponseLoadingChange,chatBoxUid,AI Chat Box,RunJS,NocoBase"
5
5
  ---
6
6
 
7
7
  # ctx.ai
8
8
 
9
9
  Use `ctx.ai` in RunJS to trigger **AI employee tasks**. It works well in JSBlock, JSAction, and other interactions where a button, form, or business flow needs to hand work to a specific AI employee.
10
10
 
11
- `ctx.ai` only triggers tasks. It does not return the execution result of the AI employee task. After the call, the task enters the AI employee conversation flow, and the result is handled by the AI employee session.
11
+ `ctx.ai` uploads AI task attachments and triggers tasks. File uploads can be awaited, but task triggering does not return the execution result of the AI employee task. After the call, the task enters the AI employee conversation flow, and the result is handled by the AI employee session.
12
12
 
13
13
  :::warning Note
14
14
 
15
- `ctx.ai` is provided by the AI plugin. If the AI plugin is not enabled, or the current RunJS environment has not loaded the corresponding client capability, `ctx.ai` may not exist. You can check `ctx.ai?.triggerTask` or `ctx.ai?.triggerModelTask` before calling it.
15
+ `ctx.ai` is provided by the AI plugin. If the AI plugin is not enabled, or the current RunJS environment has not loaded the corresponding client capability, `ctx.ai` may not exist. You can check `ctx.ai?.uploadFile`, `ctx.ai?.triggerTask`, or `ctx.ai?.triggerModelTask` before calling it.
16
16
 
17
17
  :::
18
18
 
19
19
  ## Methods
20
20
 
21
+ ### ctx.ai.uploadFile()
22
+
23
+ Upload one file and return an attachment object that can be passed directly to an AI employee task.
24
+
25
+ ```ts
26
+ const attachment = await ctx.ai.uploadFile(file, options);
27
+ ```
28
+
29
+ | Parameter | Type | Description |
30
+ |------|------|------|
31
+ | `file` | `File` | Browser file object to upload. |
32
+ | `options.onProgress` | `(percent: number) => void` | Upload progress callback. `percent` ranges from `0` to `100`. |
33
+ | `options.signal` | `AbortSignal` | Signal used to cancel the upload. |
34
+
35
+ The upload uses the file storage configured by the AI plugin and creates a record in `aiFiles`. The returned object includes fields such as `id`, `filename`, `url`, and `source`:
36
+
37
+ ```ts
38
+ const attachment = await ctx.ai.uploadFile(file, {
39
+ onProgress(percent) {
40
+ console.log('upload progress', percent);
41
+ },
42
+ });
43
+
44
+ // attachment can be placed directly in message.attachments
45
+ ```
46
+
47
+ The Promise is rejected when the upload fails. Removing an attachment from the local UI does not delete the record already created in `aiFiles`, matching the behavior of the default AI chat window.
48
+
21
49
  ### ctx.ai.triggerTask()
22
50
 
23
51
  Trigger an AI employee task directly.
@@ -30,8 +58,10 @@ ctx.ai.triggerTask(options: TriggerTaskOptions): void
30
58
  |------|------|------|
31
59
  | `aiEmployee` | `string \| AIEmployee` | AI employee. When a string is passed, NocoBase matches `AIEmployee.username` exactly, and the AI employee must be accessible to the current user. |
32
60
  | `tasks` | `Task[]` | Tasks to trigger. |
61
+ | `chatBoxUid` | `string` | FlowModel uid of the AI Chat Box block that should receive the task. |
33
62
  | `open` | `boolean` | Whether to open the AI employee conversation panel. |
34
63
  | `auto` | `boolean` | Whether to use the auto-trigger semantics of an AI employee action. |
64
+ | `onResponseLoadingChange` | `(loading: boolean) => void` | Model response loading callback. It only runs when this task is sent automatically. |
35
65
 
36
66
  Common `Task` fields:
37
67
 
@@ -40,12 +70,160 @@ Common `Task` fields:
40
70
  | `title` | `string` | Task title. |
41
71
  | `message.system` | `string` | System message, used to constrain the AI employee's role and output requirements. |
42
72
  | `message.user` | `string` | User message, which is the main instruction for this task. |
73
+ | `message.attachments` | `Attachment[]` | Attachments used by the task, usually returned by `ctx.ai.uploadFile()`. |
43
74
  | `message.workContext` | `ContextItem[]` | Page block context used by the task. |
44
75
  | `autoSend` | `boolean` | Whether to send the task message automatically. |
45
76
  | `webSearch` | `boolean` | Whether Web search is allowed for this task. |
46
77
  | `model` | `{ llmService: string; model: string } \| null` | Model used by this task. |
47
78
  | `skillSettings` | `SkillSettings` | Skills and tools available to this task. |
48
79
 
80
+ ### Track the Response Loading State
81
+
82
+ Pass `onResponseLoadingChange` in the top-level options to track the model response loading state for this task. The callback receives `true` when NocoBase starts waiting for the model response, and `false` when the response completes, is canceled, or fails. If the React component has declared `setResponseLoading` with `useState`, you can write:
83
+
84
+ ```tsx
85
+ ctx.ai.triggerTask({
86
+ aiEmployee: 'nathan',
87
+ open: true,
88
+ tasks: [
89
+ {
90
+ title: ctx.t('Review current page'),
91
+ message: {
92
+ user: 'Review the current page and summarize the main risks.',
93
+ },
94
+ autoSend: true,
95
+ },
96
+ ],
97
+ onResponseLoadingChange(loading) {
98
+ setResponseLoading(loading);
99
+ },
100
+ });
101
+ ```
102
+
103
+ `onResponseLoadingChange` only tracks the model response started directly by this `triggerTask()` call. With `autoSend: false`, the task is placed in the chat draft and the callback does not run. If the user sends the draft later, that manual send does not reuse this callback.
104
+
105
+ In a React component inside a JS block, this state update rerenders the component while it remains mounted.
106
+
107
+ ### Target an AI Chat Box
108
+
109
+ Set `chatBoxUid` on the top-level `triggerTask()` options to trigger the task in a mounted AI Chat Box block instead of the global AI employee dialog.
110
+
111
+ ```ts
112
+ ctx.ai.triggerTask({
113
+ aiEmployee: 'nathan',
114
+ chatBoxUid: 'AI_CHAT_BOX_BLOCK_UID',
115
+ open: true,
116
+ tasks: [
117
+ {
118
+ title: ctx.t('Review current page'),
119
+ message: {
120
+ user: 'Review the current page and summarize the main risks.',
121
+ },
122
+ },
123
+ ],
124
+ });
125
+ ```
126
+
127
+ The uid must belong to the outer AI Chat Box block currently mounted on the page. Do not put this routing value inside `tasks`. If the target block cannot be found, NocoBase reports an error and does not fall back to the global dialog. When `chatBoxUid` is omitted, the task uses the global AI employee dialog.
128
+
129
+ ### Upload and Send Attachments in JSBlock
130
+
131
+ The following example renders file upload, task instructions, and a send button in JSBlock. Uploaded files are passed to the AI employee through `message.attachments`:
132
+
133
+ ```tsx
134
+ if (!ctx.ai?.uploadFile || !ctx.ai?.triggerTask) {
135
+ ctx.message.error(ctx.t('AI employee task API is not available.'));
136
+ return;
137
+ }
138
+
139
+ const { React } = ctx.libs;
140
+ const { useState } = React;
141
+ const { Button, Card, Input, Space, Upload } = ctx.libs.antd;
142
+ const { InboxOutlined, SendOutlined } = ctx.libs.antdIcons;
143
+
144
+ const AttachmentTask = () => {
145
+ const [prompt, setPrompt] = useState('');
146
+ const [fileList, setFileList] = useState([]);
147
+
148
+ const uploadAttachment = async ({ file, onError, onProgress, onSuccess }) => {
149
+ try {
150
+ const attachment = await ctx.ai.uploadFile(file, {
151
+ onProgress(percent) {
152
+ onProgress?.({ percent });
153
+ },
154
+ });
155
+ onSuccess?.(attachment);
156
+ } catch (error) {
157
+ onError?.(error instanceof Error ? error : new Error(ctx.t('File upload failed')));
158
+ }
159
+ };
160
+
161
+ const sendTask = () => {
162
+ const attachments = fileList
163
+ .filter((file) => file.status === 'done' && file.response)
164
+ .map((file) => file.response);
165
+
166
+ if (!prompt.trim()) {
167
+ ctx.message.warning(ctx.t('Enter task instructions'));
168
+ return;
169
+ }
170
+
171
+ ctx.ai.triggerTask({
172
+ aiEmployee: 'viz',
173
+ open: true,
174
+ tasks: [
175
+ {
176
+ title: ctx.t('Analyze uploaded files'),
177
+ message: {
178
+ user: prompt.trim(),
179
+ attachments,
180
+ },
181
+ autoSend: true,
182
+ },
183
+ ],
184
+ });
185
+ setPrompt('');
186
+ setFileList([]);
187
+ };
188
+
189
+ const uploading = fileList.some((file) => file.status === 'uploading');
190
+
191
+ return (
192
+ <Card title={ctx.t('AI file analysis')}>
193
+ <Space direction="vertical" size="middle" style={{ width: '100%' }}>
194
+ <Upload.Dragger
195
+ multiple
196
+ fileList={fileList}
197
+ customRequest={uploadAttachment}
198
+ onChange={({ fileList: nextFileList }) => setFileList(nextFileList)}
199
+ >
200
+ <p className="ant-upload-drag-icon"><InboxOutlined /></p>
201
+ <p>{ctx.t('Click or drag files here to upload')}</p>
202
+ </Upload.Dragger>
203
+ <Input.TextArea
204
+ value={prompt}
205
+ onChange={(event) => setPrompt(event.target.value)}
206
+ placeholder={ctx.t('Describe the task for the AI employee')}
207
+ autoSize={{ minRows: 3, maxRows: 8 }}
208
+ />
209
+ <Button
210
+ type="primary"
211
+ icon={<SendOutlined />}
212
+ disabled={uploading || !prompt.trim()}
213
+ onClick={sendTask}
214
+ >
215
+ {ctx.t('Send to AI')}
216
+ </Button>
217
+ </Space>
218
+ </Card>
219
+ );
220
+ };
221
+
222
+ ctx.render(<AttachmentTask />);
223
+ ```
224
+
225
+ With `autoSend: false`, the attachments and task instructions are placed in the AI chat draft instead of being sent immediately.
226
+
49
227
  ### Add Page Block Context
50
228
 
51
229
  `message.workContext` currently passes page blocks. Put the FlowModel uid of the target page block into it:
@@ -163,9 +341,15 @@ ctx.ai.triggerModelTask(uid: string, taskIndex: number, options?: TriggerModelTa
163
341
  | `taskIndex` | `number` | Task index, starting from `0`. |
164
342
  | `options.open` | `boolean` | Whether to open the AI employee conversation panel. |
165
343
  | `options.auto` | `boolean` | Whether to use the auto-trigger semantics of an AI employee action. |
344
+ | `options.attachments` | `Attachment[]` | Attachments dynamically appended to the configured task. |
345
+ | `options.onResponseLoadingChange` | `(loading: boolean) => void` | Model response loading callback. It only runs when the configured task is sent automatically. |
166
346
 
167
347
  This method reads the AI employee and task configuration from the target model. It is useful when the task has already been configured on an AI employee action on the page, and RunJS only needs to trigger it.
168
348
 
349
+ The public `triggerModelTask()` options do not accept `chatBoxUid`. To target an AI Chat Box, configure `chatBoxUid` on the preset task of the AI employee action. `triggerModelTask()` continues to reuse that preset value.
350
+
351
+ `options.onResponseLoadingChange` behaves the same as the option on `triggerTask()`. Whether it runs depends on the configured task's `autoSend` value. It does not run when that task uses `autoSend: false`.
352
+
169
353
  ```ts
170
354
  if (!ctx.ai?.triggerModelTask) {
171
355
  ctx.message.error(ctx.t('AI employee task API is not available.'));
@@ -176,6 +360,7 @@ const weeklyReviewActionUid = 'AI_EMPLOYEE_ACTION_MODEL_UID';
176
360
 
177
361
  ctx.ai.triggerModelTask(weeklyReviewActionUid, 0, {
178
362
  open: true,
363
+ attachments,
179
364
  });
180
365
 
181
366
  ctx.message.success(ctx.t('Configured AI employee task triggered.'));
@@ -195,9 +380,14 @@ If the target model does not exist, has no AI employee configured, or the specif
195
380
  ## Notes
196
381
 
197
382
  - `triggerTask()` and `triggerModelTask()` are fire-and-forget. They do not return the execution result of the AI employee task.
383
+ - `uploadFile()` returns a Promise. Wait for the upload to finish before triggering a task that uses the attachment.
198
384
  - `aiEmployee` strings only match `AIEmployee.username` exactly. They do not match nicknames, job titles, or translated names.
199
385
  - `triggerModelTask()` uses a `0`-based `taskIndex`.
200
386
  - `triggerModelTask()` reads task configuration from the target AI employee action model. If the task needs work context, configure `message.workContext` on that task.
387
+ - Top-level `triggerTask().chatBoxUid` must reference an AI Chat Box block currently mounted on the page.
388
+ - `triggerModelTask()` keeps using `chatBoxUid` configured on its preset task.
389
+ - Dynamic `triggerModelTask()` attachments are appended to the preset task's existing `message.attachments` without changing the saved task configuration.
390
+ - `onResponseLoadingChange` only tracks a model response automatically sent by the current call. It does not track a message the user sends manually later.
201
391
 
202
392
  ## Related
203
393
 
@@ -213,17 +213,30 @@ If you need to store sensitive files, it is recommended to use a cloud storage s
213
213
 
214
214
  ![](https://static-docs.nocobase.com/202501031623549.png)
215
215
 
216
- For local storage or other public storage that can be accessed directly through same-origin application URLs, you should also pay extra attention to the risks introduced by active content files. Files such as `html`, `xhtml`, and `svg` may be parsed and executed directly by the browser. If an attacker can upload such a file and trick a user into opening it, the attacker may use your trusted application domain to host a malicious page or script.
216
+ For local storage or other storage that can be accessed directly through same-origin application URLs, you should also pay extra attention to the risks introduced by active content files. Files such as `html`, `xhtml`, and `svg` may be parsed and executed directly by the browser. If an attacker can upload such a file and trick a user into opening it, the attacker may use your trusted application domain to host a malicious page or script.
217
217
 
218
218
  NocoBase upload validation does not trust the `Content-Type` sent by the request. It prefers the MIME type detected on the server side. A file extension only represents the filename and should not be treated as the authoritative file content type. Therefore, when serving public uploaded files, you also need to make sure the file access path has proper security response headers.
219
219
 
220
- If you deploy with Docker or use the nginx configuration generated by NocoBase, the upload directory already includes this protection: all uploaded files return `X-Content-Type-Options: nosniff`, and active content files such as `html`, `xhtml`, `svg`, `svgz`, and `pdf` are returned as downloads through `Content-Disposition: attachment`.
220
+ If you deploy with Docker or use the nginx configuration generated by NocoBase, legacy `/storage/uploads/` URLs are restricted to signed-in users. All uploaded files also return `X-Content-Type-Options: nosniff`, and active content files such as `html`, `xhtml`, `svg`, `svgz`, and `pdf` are returned as downloads through `Content-Disposition: attachment`. New `/files/` URLs continue to enforce record-level file permissions.
221
+
222
+ If an existing integration still depends on anonymous access to legacy URLs, set `LEGACY_LOCAL_STORAGE_PUBLIC_ACCESS=true` and restart the application to restore public access to `/storage/uploads/`. This compatibility switch is disabled by default, affects only legacy URLs, and does not change record-level permissions for `/files/`. Public access may expose uploaded files, so confirm that they contain no sensitive content before enabling it.
221
223
 
222
224
  If you use a custom proxy, CDN, object storage, or expose the local upload directory directly, make sure these rules are not bypassed. You can use the following nginx configuration as a reference:
223
225
 
224
226
  ```nginx
227
+ location = /_nocobase_legacy_file_auth {
228
+ internal;
229
+ proxy_pass http://127.0.0.1:13000/api/auth:checkLegacyFileAccess;
230
+ proxy_pass_request_body off;
231
+ proxy_set_header Content-Length "";
232
+ proxy_set_header Cookie $http_cookie;
233
+ proxy_set_header Authorization $http_authorization;
234
+ }
235
+
225
236
  location ~* ^/storage/uploads/(.*\.(?:htm|html|svg|svgz|xhtml|pdf))$ {
226
237
  alias /path/to/nocobase/storage/uploads/$1;
238
+ auth_request /_nocobase_legacy_file_auth;
239
+ add_header Cache-Control "private, no-store" always;
227
240
  add_header Content-Disposition "attachment" always;
228
241
  add_header X-Content-Type-Options "nosniff" always;
229
242
  autoindex off;
@@ -231,6 +244,8 @@ location ~* ^/storage/uploads/(.*\.(?:htm|html|svg|svgz|xhtml|pdf))$ {
231
244
 
232
245
  location /storage/uploads/ {
233
246
  alias /path/to/nocobase/storage/uploads/;
247
+ auth_request /_nocobase_legacy_file_auth;
248
+ add_header Cache-Control "private, no-store" always;
234
249
  add_header X-Content-Type-Options "nosniff" always;
235
250
  autoindex off;
236
251
  }
@@ -8,6 +8,13 @@ pkg: '@nocobase/plugin-user-data-sync'
8
8
 
9
9
  This feature allows you to register and manage user data synchronization sources. By default, an HTTP API is provided, but additional data sources can be supported through plugins. It supports syncing data to the **Users** and **Departments** collections by default, with the possibility to extend synchronization to other target resources using plugins.
10
10
 
11
+ ## Available data sources
12
+
13
+ - [DingTalk](./sources/dingtalk.md) — Synchronize DingTalk users and departments, with incremental updates through HTTP callbacks or Stream mode.
14
+ - [LDAP](./sources/ldap.md) — Synchronize LDAP users and optional organizational units by reusing an LDAP authenticator.
15
+ - [WeCom](./sources/wecom.md) — Synchronize users and departments from WeCom.
16
+ - [HTTP API](./sources/api.md) — Push user and department data through the synchronization API.
17
+
11
18
  ## Data Source Management and Synchronization
12
19
 
13
20
 
@@ -51,4 +58,4 @@ For failed synchronization tasks, you can click **Retry**.
51
58
  In case of synchronization failures, you can troubleshoot the issue through system logs. Additionally, raw synchronization records are stored in the `user-data-sync` directory under the application logs folder.
52
59
 
53
60
 
54
- ![](https://static-docs.nocobase.com/202412041205655.png)
61
+ ![](https://static-docs.nocobase.com/202412041205655.png)
@@ -0,0 +1,138 @@
1
+ ---
2
+ pkg: '@nocobase/plugin-auth-dingtalk'
3
+ title: "Synchronize User Data from DingTalk"
4
+ description: "Synchronize DingTalk users and departments to NocoBase and receive incremental changes through HTTP callbacks or Stream mode."
5
+ keywords: "DingTalk,user synchronization,department synchronization,Stream mode,event subscription,NocoBase"
6
+ ---
7
+
8
+ # Synchronize User Data from DingTalk
9
+
10
+ <PluginInfo commercial="true" name="auth-dingtalk"></PluginInfo>
11
+
12
+ ## Introduction
13
+
14
+ The **DingTalk** plugin synchronizes users and departments from a DingTalk organization to NocoBase. It supports full synchronization on demand and incremental updates through either an HTTP callback or a Stream connection.
15
+
16
+ ## Before you begin
17
+
18
+ 1. Install and enable the **DingTalk** and **User Data Synchronization** plugins.
19
+ 2. Create an internal application in the DingTalk developer console.
20
+ 3. Grant the contact permissions and configure the data permission scope described below.
21
+ 4. Copy the application's Client ID and Client Secret. See [Authentication: DingTalk](/auth-verification/auth-dingtalk/) for the credential setup.
22
+
23
+ ## Configure contact permissions and the data permission scope
24
+
25
+ Open **Permission Management** for the application in the DingTalk developer console and grant the following contact permissions.
26
+
27
+ | Permission | Identifier | Required | Purpose |
28
+ | --- | --- | --- | --- |
29
+ | Read department information | `qyapi_get_department_list` | Yes | Read the department list, names, and hierarchy. |
30
+ | Read department members | `qyapi_get_department_member` | Yes | Read the member list of each department. |
31
+ | Read member information | `qyapi_get_member` | Yes | Read member details and department memberships. |
32
+ | Employee mobile number information | `fieldMobile` | When using mobile numbers | Synchronize mobile numbers. This permission is required when **User unique identifier field** is `mobile`. |
33
+ | Email and other personal information | `fieldEmail` | No | Grant this permission when user email addresses need to be synchronized. |
34
+
35
+ After granting the permissions, configure the application's **Data Permission Scope** (also called **Contact Permission Scope** or **Visibility Range** in some console versions) to include the departments and employees that may be synchronized. Select all employees for a full organization synchronization. If only selected departments or employees are included, NocoBase synchronizes only those entries.
36
+
37
+ :::warning
38
+ API permissions determine which fields the application can read, while the data permission scope determines which departments and employees it can read. Both must be configured. Event subscriptions do not replace contact read permissions: after receiving an event, NocoBase still calls DingTalk APIs to retrieve the latest user or department information.
39
+ :::
40
+
41
+ If the same DingTalk application is also used for sign-in, grant the personal-information permissions described in [Authentication: DingTalk](/auth-verification/auth-dingtalk/). Those sign-in permissions are not required solely for user data synchronization.
42
+
43
+ ## Add a DingTalk synchronization source
44
+
45
+ Go to **Users & Permissions > Synchronize**, click **Add new**, and select **DingTalk** as the type.
46
+
47
+ Configure the following fields:
48
+
49
+ | Field | Description |
50
+ | --- | --- |
51
+ | Source name | A unique name for this synchronization source. |
52
+ | Enabled | Starts event reception for this source and enables synchronization tasks. |
53
+ | Client ID | The Client ID of the DingTalk internal application. Environment variables and secrets are supported. |
54
+ | Client Secret | The Client Secret of the DingTalk internal application. Environment variables and secrets are supported. |
55
+ | User unique identifier field | Select `mobile` or `unionId`. Keep the selected field stable after the first synchronization. Users without a value for the selected field are skipped. |
56
+ | Event receiving mode | Select **HTTP callback** or **Stream mode** for incremental user and department changes. |
57
+
58
+ Save and enable the source, then click **Sync** to complete the initial full synchronization before relying on incremental events.
59
+
60
+ ## Choose an event receiving mode
61
+
62
+ ### Stream mode
63
+
64
+ Stream mode establishes an outbound persistent connection from the NocoBase server to DingTalk. It does not require a public callback URL, Token, or EncodingAESKey.
65
+
66
+ 1. In the DingTalk developer console, open the application's event subscription settings and select **Stream mode**.
67
+ 2. Subscribe to the user and department change events required by the application.
68
+ 3. In NocoBase, select **Stream mode**, save the source, and enable it.
69
+
70
+ The Stream client starts when the source is enabled. Updating, disabling, or deleting the source refreshes or closes the corresponding connection.
71
+
72
+ :::info
73
+ The NocoBase server must be able to establish outbound connections to DingTalk. A reverse proxy or public inbound callback endpoint is not required for Stream mode.
74
+ :::
75
+
76
+ ### HTTP callback
77
+
78
+ HTTP callback mode receives DingTalk events through a NocoBase callback URL.
79
+
80
+ 1. Select **HTTP callback** in NocoBase.
81
+ 2. Enter the Token and EncodingAESKey configured for the DingTalk event subscription.
82
+ 3. Save the source and copy the generated **Event callback URL**.
83
+ 4. Configure that URL in the DingTalk developer console and subscribe to the required user and department events.
84
+
85
+ The callback URL must be reachable by DingTalk. In a production environment, expose it through HTTPS and make sure the reverse proxy forwards the request path unchanged.
86
+
87
+ ## Supported incremental events
88
+
89
+ Both event receiving modes handle the following DingTalk events:
90
+
91
+ | Event | Result in NocoBase |
92
+ | --- | --- |
93
+ | `user_add_org` | Create or update the user. |
94
+ | `user_modify_org` | Update the user. |
95
+ | `user_leave_org` | Delete the synchronized user. |
96
+ | `org_dept_create` | Create or update the department. |
97
+ | `org_dept_modify` | Update the department and synchronize its users. |
98
+ | `org_dept_remove` | Delete the synchronized department. |
99
+
100
+ ## Synchronized fields
101
+
102
+ ### Department fields
103
+
104
+ | DingTalk field | NocoBase field or purpose |
105
+ | --- | --- |
106
+ | `dept_id` | Source-unique department identifier. |
107
+ | `name` | Department name. |
108
+ | `parent_id` | Parent department used to build the department hierarchy. If the parent is outside the data permission scope, the department is synchronized as a root department. |
109
+
110
+ ### User fields
111
+
112
+ | DingTalk field | NocoBase field or purpose |
113
+ | --- | --- |
114
+ | `mobile` or `unionid` | Generates the source-unique user identifier and username according to **User unique identifier field**. A user without the selected field is skipped. |
115
+ | `name` | User nickname. |
116
+ | `mobile` | Phone number. Requires the **Employee mobile number information** permission. |
117
+ | `email`, falling back to `org_email` | Email address. Requires the **Email and other personal information** permission. |
118
+ | `dept_id_list` | Department memberships. Only departments within the data permission scope are retained. |
119
+ | `dept_order_list` | Primary department. |
120
+ | `leader_in_dept` | Whether the user is an owner of the corresponding department. |
121
+
122
+ ### Department owners
123
+
124
+ DingTalk uses `leader_in_dept` in the user details to indicate whether the user is an owner of each department they belong to. NocoBase synchronizes this flag separately for each department: the same user can own multiple departments, and an owned department does not have to be the user's primary department. Only departments within the data permission scope are included.
125
+
126
+ When an owner flag is removed in DingTalk, the corresponding owner flag in NocoBase is removed by the next synchronization. Owner status changed manually in NocoBase may be overwritten by DingTalk data during the next synchronization.
127
+
128
+ Full and incremental synchronization use the same field mapping. Other DingTalk user fields, such as avatar, job title, and employee number, are not currently synchronized.
129
+
130
+ ## Troubleshooting
131
+
132
+ - If synchronization returns no data or an entire department is missing, verify the three required contact read permissions and confirm that the department is included in the data permission scope.
133
+ - If a user is present but their mobile number or email address is empty, verify the **Employee mobile number information** or **Email and other personal information** permission respectively.
134
+ - If DingTalk reports that a department or employee is outside the permission scope, expand the application's data permission scope instead of only resubscribing to events.
135
+ - If users are skipped, verify that they have a value for the configured unique identifier field.
136
+ - For Stream mode, check the application logs for `Dingtalk stream client starting`, `Dingtalk stream client started`, or connection errors.
137
+ - For HTTP callback mode, verify that the callback URL is publicly reachable and that Token and EncodingAESKey match the DingTalk configuration.
138
+ - Run a manual full synchronization after changing the application's permissions or visibility range.