springbootAI 2.3.8__tar.gz → 2.3.9__tar.gz

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 (365) hide show
  1. {springbootai-2.3.8 → springbootai-2.3.9}/CHANGELOG.md +9 -0
  2. {springbootai-2.3.8/springbootAI.egg-info → springbootai-2.3.9}/PKG-INFO +21 -7
  3. {springbootai-2.3.8 → springbootai-2.3.9}/README.md +20 -6
  4. {springbootai-2.3.8 → springbootai-2.3.9}/pyproject.toml +2 -1
  5. {springbootai-2.3.8 → springbootai-2.3.9/springbootAI.egg-info}/PKG-INFO +21 -7
  6. {springbootai-2.3.8 → springbootai-2.3.9}/springbootAI.egg-info/SOURCES.txt +7 -0
  7. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/__init__.py +1 -1
  8. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/ai/__init__.py +15 -7
  9. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/ai/advisors.py +55 -10
  10. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/ai/annotation_runtime.py +18 -6
  11. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/ai/autoconfig.py +53 -4
  12. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/ai/core.py +154 -30
  13. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/ai/etl.py +73 -12
  14. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/ai/memory.py +50 -26
  15. springbootai-2.3.9/springbootai/ai/providers.py +1521 -0
  16. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/ai/resilience.py +22 -9
  17. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/ai/tools.py +100 -10
  18. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/ai/vectorstore.py +41 -3
  19. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/annotations/core.py +4 -1
  20. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/cli/scaffold.py +33 -4
  21. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/cloud/__init__.py +4 -1
  22. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/cloud/bus.py +64 -12
  23. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/cloud/config_center.py +215 -37
  24. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/cloud/discovery.py +102 -23
  25. springbootai-2.3.9/springbootai/cloud/feign.py +608 -0
  26. springbootai-2.3.9/springbootai/cloud/gateway.py +880 -0
  27. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/cloud/seata.py +176 -47
  28. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/config/spring-configuration-metadata.json +10 -1
  29. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/csv/__init__.py +1 -1
  30. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/data/__init__.py +1 -1
  31. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/datasource/__init__.py +1 -1
  32. springbootai-2.3.9/springbootai/devtools.py +243 -0
  33. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/excel/__init__.py +1 -1
  34. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/i18n/__init__.py +1 -1
  35. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/__init__.py +1 -1
  36. springbootai-2.3.9/springbootai/logging/__init__.py +13 -0
  37. springbootai-2.3.9/springbootai/logging/context.py +213 -0
  38. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/logging/loguru_logger.py +107 -13
  39. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/main.py +163 -46
  40. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/mcp/client.py +11 -1
  41. springbootai-2.3.9/springbootai/monitoring/admin_client.py +266 -0
  42. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/__init__.py +1 -1
  43. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/version.py +1 -1
  44. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/test/__init__.py +1 -1
  45. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/tracing/skywalking.py +72 -27
  46. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/tx/__init__.py +1 -1
  47. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/utils/banner.py +2 -2
  48. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/validation/__init__.py +1 -1
  49. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/web/request_metrics.py +4 -4
  50. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/web/swagger.py +1 -1
  51. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/web/web_context.py +67 -11
  52. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/websocket/__init__.py +1 -1
  53. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_ai_comprehensive.py +9 -5
  54. springbootai-2.3.9/tests/test_ai_enterprise_hardening.py +349 -0
  55. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_ai_module.py +7 -8
  56. springbootai-2.3.9/tests/test_ai_stream_hardening.py +461 -0
  57. springbootai-2.3.9/tests/test_cloud_log_safety.py +260 -0
  58. springbootai-2.3.9/tests/test_config_admin_hardening.py +207 -0
  59. springbootai-2.3.9/tests/test_devtools_lifecycle_hardening.py +193 -0
  60. springbootai-2.3.9/tests/test_io_http_logging_hardening.py +847 -0
  61. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_tracing.py +3 -6
  62. springbootai-2.3.8/springbootai/ai/providers.py +0 -881
  63. springbootai-2.3.8/springbootai/cloud/feign.py +0 -469
  64. springbootai-2.3.8/springbootai/cloud/gateway.py +0 -542
  65. springbootai-2.3.8/springbootai/devtools.py +0 -153
  66. springbootai-2.3.8/springbootai/logging/__init__.py +0 -1
  67. springbootai-2.3.8/springbootai/monitoring/admin_client.py +0 -77
  68. {springbootai-2.3.8 → springbootai-2.3.9}/LICENSE +0 -0
  69. {springbootai-2.3.8 → springbootai-2.3.9}/MANIFEST.in +0 -0
  70. {springbootai-2.3.8 → springbootai-2.3.9}/SECURITY.md +0 -0
  71. {springbootai-2.3.8 → springbootai-2.3.9}/requirements-ai.txt +0 -0
  72. {springbootai-2.3.8 → springbootai-2.3.9}/requirements-langgraph.txt +0 -0
  73. {springbootai-2.3.8 → springbootai-2.3.9}/requirements-mcp.txt +0 -0
  74. {springbootai-2.3.8 → springbootai-2.3.9}/requirements.txt +0 -0
  75. {springbootai-2.3.8 → springbootai-2.3.9}/setup.cfg +0 -0
  76. {springbootai-2.3.8 → springbootai-2.3.9}/setup.py +0 -0
  77. {springbootai-2.3.8 → springbootai-2.3.9}/springbootAI.egg-info/dependency_links.txt +0 -0
  78. {springbootai-2.3.8 → springbootai-2.3.9}/springbootAI.egg-info/entry_points.txt +0 -0
  79. {springbootai-2.3.8 → springbootai-2.3.9}/springbootAI.egg-info/requires.txt +0 -0
  80. {springbootai-2.3.8 → springbootai-2.3.9}/springbootAI.egg-info/top_level.txt +0 -0
  81. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/ai/annotations.py +0 -0
  82. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/ai/observability.py +0 -0
  83. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/annotations/__init__.py +0 -0
  84. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/annotations/batch.py +0 -0
  85. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/annotations/cache.py +0 -0
  86. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/annotations/cloud.py +0 -0
  87. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/annotations/conditional.py +0 -0
  88. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/annotations/data.py +0 -0
  89. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/annotations/enterprise.py +0 -0
  90. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/annotations/langchain.py +0 -0
  91. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/annotations/langgraph.py +0 -0
  92. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/annotations/lombok.py +0 -0
  93. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/annotations/messaging.py +0 -0
  94. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/annotations/security.py +0 -0
  95. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/aop/__init__.py +0 -0
  96. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/aop/aspect.py +0 -0
  97. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/aop/cloud_aop.py +0 -0
  98. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/aop/comprehensive_aop.py +0 -0
  99. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/aop/method_interceptor.py +0 -0
  100. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/aop/proxy_factory.py +0 -0
  101. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/batch/__init__.py +0 -0
  102. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/cli/__init__.py +0 -0
  103. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/cli/main.py +0 -0
  104. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/cloud/load_balancer.py +0 -0
  105. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/cloud/nacos_config.py +0 -0
  106. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/cloud/seata_at_proxy.py +0 -0
  107. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/cloud/seata_bridge.py +0 -0
  108. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/cloud/sentinel.py +0 -0
  109. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/cloud/tracer.py +0 -0
  110. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/cloud/transaction_store.py +0 -0
  111. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/config/__init__.py +0 -0
  112. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/config/binding.py +0 -0
  113. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/config/config_loader.py +0 -0
  114. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/config/config_monitor.py +0 -0
  115. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/context/__init__.py +0 -0
  116. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/context/application_context.py +0 -0
  117. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/context/bean_definition.py +0 -0
  118. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/context/bean_factory.py +0 -0
  119. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/context/lifecycle.py +0 -0
  120. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/context/registry.py +0 -0
  121. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/context/scanner.py +0 -0
  122. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/core/__init__.py +0 -0
  123. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/core/graceful_shutdown.py +0 -0
  124. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/core/typing_utils.py +0 -0
  125. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/csv/annotations.py +0 -0
  126. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/csv/converters.py +0 -0
  127. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/csv/easy_csv.py +0 -0
  128. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/csv/exceptions.py +0 -0
  129. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/csv/reader.py +0 -0
  130. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/csv/writer.py +0 -0
  131. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/data/page.py +0 -0
  132. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/data/repository.py +0 -0
  133. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/data/rest.py +0 -0
  134. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/data/specification.py +0 -0
  135. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/datasource/annotations.py +0 -0
  136. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/datasource/context.py +0 -0
  137. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/datasource/dynamic.py +0 -0
  138. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/event/__init__.py +0 -0
  139. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/event/publisher.py +0 -0
  140. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/excel/annotations.py +0 -0
  141. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/excel/converters.py +0 -0
  142. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/excel/easy_excel.py +0 -0
  143. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/excel/exceptions.py +0 -0
  144. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/excel/reader.py +0 -0
  145. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/excel/style.py +0 -0
  146. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/excel/writer.py +0 -0
  147. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/i18n/accessor.py +0 -0
  148. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/i18n/auto_config.py +0 -0
  149. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/i18n/holder.py +0 -0
  150. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/i18n/locale.py +0 -0
  151. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/i18n/locale_resolver.py +0 -0
  152. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/i18n/message_source.py +0 -0
  153. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/i18n/middleware.py +0 -0
  154. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/i18n/properties.py +0 -0
  155. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/i18n/sources.py +0 -0
  156. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/adapters.py +0 -0
  157. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/agents/__init__.py +0 -0
  158. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/agents/services.py +0 -0
  159. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/annotations.py +0 -0
  160. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/autoconfig.py +0 -0
  161. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/callbacks/__init__.py +0 -0
  162. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/callbacks/handlers.py +0 -0
  163. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/chains/__init__.py +0 -0
  164. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/chains/services.py +0 -0
  165. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/core.py +0 -0
  166. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/indexes/__init__.py +0 -0
  167. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/indexes/index.py +0 -0
  168. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/loaders/__init__.py +0 -0
  169. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/loaders/loaders.py +0 -0
  170. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/memory/__init__.py +0 -0
  171. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/memory/memory.py +0 -0
  172. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/parsers/__init__.py +0 -0
  173. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/parsers/parsers.py +0 -0
  174. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/partners.py +0 -0
  175. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/prompts/__init__.py +0 -0
  176. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/prompts/templates.py +0 -0
  177. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/retrievers/__init__.py +0 -0
  178. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/retrievers/retrievers.py +0 -0
  179. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/tools/__init__.py +0 -0
  180. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/tools/tools.py +0 -0
  181. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/utilities/__init__.py +0 -0
  182. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/utilities/utils.py +0 -0
  183. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/vectorstores/__init__.py +0 -0
  184. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langchain/vectorstores/stores.py +0 -0
  185. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langgraph/__init__.py +0 -0
  186. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langgraph/annotation_runtime.py +0 -0
  187. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langgraph/annotations.py +0 -0
  188. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langgraph/autoconfig.py +0 -0
  189. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langgraph/checkpoint.py +0 -0
  190. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langgraph/config.py +0 -0
  191. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/langgraph/runtime.py +0 -0
  192. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/mcp/__init__.py +0 -0
  193. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/mcp/annotation_runtime.py +0 -0
  194. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/mcp/annotations.py +0 -0
  195. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/mcp/autoconfig.py +0 -0
  196. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/mcp/config.py +0 -0
  197. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/mcp/server.py +0 -0
  198. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/messaging/__init__.py +0 -0
  199. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/messaging/kafka.py +0 -0
  200. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/messaging/rabbitmq.py +0 -0
  201. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/monitoring/__init__.py +0 -0
  202. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/monitoring/prometheus.py +0 -0
  203. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/__init__.py +0 -0
  204. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/database.py +0 -0
  205. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/ddl_auto.py +0 -0
  206. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/migration.py +0 -0
  207. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/mybatis_integration.py +0 -0
  208. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/annotations/__init__.py +0 -0
  209. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/annotations/annotations.py +0 -0
  210. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/cache/__init__.py +0 -0
  211. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/cache/cache.py +0 -0
  212. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/cache/redis_cache.py +0 -0
  213. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/circuit_breaker/__init__.py +0 -0
  214. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/circuit_breaker/circuit_breaker.py +0 -0
  215. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/configuration.py +0 -0
  216. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/core/__init__.py +0 -0
  217. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/core/sql_session.py +0 -0
  218. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/core/sql_session_factory.py +0 -0
  219. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/dialect/__init__.py +0 -0
  220. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/dialect/dialect.py +0 -0
  221. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/dynamic_sql/__init__.py +0 -0
  222. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/dynamic_sql/dynamic_sql.py +0 -0
  223. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/interceptor/__init__.py +0 -0
  224. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/interceptor/interceptor.py +0 -0
  225. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/mapper/__init__.py +0 -0
  226. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/mapper/mapper.py +0 -0
  227. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/metrics/__init__.py +0 -0
  228. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/metrics/metrics.py +0 -0
  229. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/pool/__init__.py +0 -0
  230. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/pool/connection_pool.py +0 -0
  231. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/security/__init__.py +0 -0
  232. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/security/access_control.py +0 -0
  233. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/security/password_encoder.py +0 -0
  234. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/security/sensitive_data_masker.py +0 -0
  235. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/security/sql_injection_detector.py +0 -0
  236. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/transaction/__init__.py +0 -0
  237. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/transaction/transaction.py +0 -0
  238. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/type_handler/__init__.py +0 -0
  239. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/type_handler/type_handler.py +0 -0
  240. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/xml_parser/__init__.py +0 -0
  241. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/orm/pymybatis/xml_parser/xml_parser.py +0 -0
  242. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/retry/__init__.py +0 -0
  243. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/retry/recovery.py +0 -0
  244. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/retry/retry_annotations.py +0 -0
  245. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/retry/retry_decorator.py +0 -0
  246. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/scheduling/__init__.py +0 -0
  247. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/scheduling/scheduler.py +0 -0
  248. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/security/__init__.py +0 -0
  249. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/security/jwt_utils.py +0 -0
  250. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/security/oauth2.py +0 -0
  251. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/security/replay_protection.py +0 -0
  252. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/security/secret_manager.py +0 -0
  253. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/security/security_aop.py +0 -0
  254. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/security/security_context.py +0 -0
  255. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/test/slicing.py +0 -0
  256. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/tracing/__init__.py +0 -0
  257. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/tx/events.py +0 -0
  258. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/tx/synchronization.py +0 -0
  259. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/utils/__init__.py +0 -0
  260. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/utils/bean_utils.py +0 -0
  261. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/utils/logger.py +0 -0
  262. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/utils/redis_client.py +0 -0
  263. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/validation/aop.py +0 -0
  264. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/validation/constraints.py +0 -0
  265. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/validation/exceptions.py +0 -0
  266. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/validation/validator.py +0 -0
  267. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/web/__init__.py +0 -0
  268. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/web/actuator.py +0 -0
  269. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/web/csrf.py +0 -0
  270. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/web/exception_handler.py +0 -0
  271. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/web/hateoas.py +0 -0
  272. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/web/health.py +0 -0
  273. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/web/interceptor.py +0 -0
  274. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/web/result.py +0 -0
  275. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/websocket/annotations.py +0 -0
  276. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/websocket/broker.py +0 -0
  277. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/websocket/exceptions.py +0 -0
  278. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/websocket/handler.py +0 -0
  279. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/websocket/router.py +0 -0
  280. {springbootai-2.3.8 → springbootai-2.3.9}/springbootai/websocket/session.py +0 -0
  281. {springbootai-2.3.8 → springbootai-2.3.9}/sql/seata_undo_log.sql +0 -0
  282. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_actuator.py +0 -0
  283. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_actuator_prometheus_admin.py +0 -0
  284. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_ai_annotations.py +0 -0
  285. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_ai_declarative_annotations.py +0 -0
  286. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_annotation_combinations.py +0 -0
  287. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_annotations_contract.py +0 -0
  288. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_aop_annotations_full.py +0 -0
  289. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_aop_pointcut_enhancements.py +0 -0
  290. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_audit_time.py +0 -0
  291. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_batch.py +0 -0
  292. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_bean_utils.py +0 -0
  293. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_bus.py +0 -0
  294. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_cache_annotations.py +0 -0
  295. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_cli.py +0 -0
  296. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_cloud_embedded_full.py +0 -0
  297. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_component_init_error.py +0 -0
  298. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_compositional_annotations.py +0 -0
  299. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_conditional_annotations.py +0 -0
  300. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_config_binding.py +0 -0
  301. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_config_center.py +0 -0
  302. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_config_center_hardening.py +0 -0
  303. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_config_fixes_185.py +0 -0
  304. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_config_monitor.py +0 -0
  305. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_connection_resilience.py +0 -0
  306. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_core.py +0 -0
  307. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_core_annotations_full.py +0 -0
  308. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_csrf.py +0 -0
  309. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_csv_module.py +0 -0
  310. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_data_repository.py +0 -0
  311. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_data_rest.py +0 -0
  312. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_datasource_routing.py +0 -0
  313. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_ddl_auto.py +0 -0
  314. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_declarative_aop_post_authorize_recover.py +0 -0
  315. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_devtools.py +0 -0
  316. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_di_config_event_full.py +0 -0
  317. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_excel_module.py +0 -0
  318. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_hateoas.py +0 -0
  319. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_i18n_module.py +0 -0
  320. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_ioc_lifecycle_enhancements.py +0 -0
  321. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_jpa_version_transient.py +0 -0
  322. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_kafka.py +0 -0
  323. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_langchain_comprehensive.py +0 -0
  324. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_langchain_ext.py +0 -0
  325. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_langchain_module.py +0 -0
  326. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_langgraph_comprehensive.py +0 -0
  327. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_langgraph_module.py +0 -0
  328. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_logging_config.py +0 -0
  329. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_lombok_annotations.py +0 -0
  330. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_mcp_module.py +0 -0
  331. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_metadata.py +0 -0
  332. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_migration.py +0 -0
  333. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_nacos_config.py +0 -0
  334. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_new_annotations.py +0 -0
  335. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_new_features.py +0 -0
  336. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_oauth2.py +0 -0
  337. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_optional_component_timeouts.py +0 -0
  338. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_orm_pymybatis_full.py +0 -0
  339. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_production_readiness.py +0 -0
  340. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_pymybatis_configuration_hardening.py +0 -0
  341. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_pymybatis_contract.py +0 -0
  342. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_request_metrics.py +0 -0
  343. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_retry.py +0 -0
  344. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_runtime_configuration_fixes.py +0 -0
  345. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_scaffold_hardening.py +0 -0
  346. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_scheduling.py +0 -0
  347. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_seata_at_proxy.py +0 -0
  348. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_seata_bridge.py +0 -0
  349. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_seata_durable_store.py +0 -0
  350. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_security.py +0 -0
  351. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_security_full.py +0 -0
  352. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_security_hardening.py +0 -0
  353. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_select_page.py +0 -0
  354. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_starter.py +0 -0
  355. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_startup_lifecycle.py +0 -0
  356. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_swagger_module.py +0 -0
  357. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_test_slicing.py +0 -0
  358. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_transactional_events.py +0 -0
  359. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_validation_module.py +0 -0
  360. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_web_annotations_full.py +0 -0
  361. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_web_file_upload.py +0 -0
  362. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_web_root_mapping.py +0 -0
  363. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_web_security_responses.py +0 -0
  364. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_web_static_files.py +0 -0
  365. {springbootai-2.3.8 → springbootai-2.3.9}/tests/test_websocket_module.py +0 -0
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.3.9] - 2026-08-28
4
+
5
+ - 加固 OpenAI 兼容接口与 Ollama 的同步/异步流式协议:校验终止帧、错误信封和畸形响应,限制事件与响应大小,并完善超时、有限重试、重定向拒绝及 SDK 重试边界。
6
+ - 修复 AI 异步流阻塞事件循环、请求参数覆盖受保护字段、输出 Token 上限绕过、工具调用闭环和多租户 Memory/RAG 隔离等问题。
7
+ - 加固 Feign、Gateway、Config Center、Admin 与 Discovery:正确释放响应、执行路由谓词和过滤器、过滤逐跳头、传播请求 ID,并增加路径、响应大小、故障回退与生命周期保护。
8
+ - 新增统一日志脱敏和日志注入防护,覆盖异常链、Bearer/Basic/Cookie、云事件、Nacos、Seata 与 SkyWalking,避免敏感负载进入日志或健康响应。
9
+ - 修复原子脚手架写入、TextReader 文件边界、DevTools 停止/重启语义、SkyWalking 显式初始化和 Banner 版本读取错误。
10
+ - 新增企业加固回归测试;完整测试结果为 3170 passed、11 skipped、0 failed,Bandit 中高危扫描为 0。
11
+
3
12
  ## [2.3.8] - 2026-08-24
4
13
 
5
14
  - 修复配置加载的原子性与数据库 URL 优先级:请求监控不再误落到根目录 `test.db`,SQLite 运行目录会自动创建,显式 URL/驱动/数据库名称按统一优先级生效。
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: springbootAI
3
- Version: 2.3.8
3
+ Version: 2.3.9
4
4
  Summary: Spring-style Python framework with Web, ORM, Cloud and AI integrations
5
5
  Author-email: YuConggen <1516933915@qq.com>
6
6
  License-Expression: MIT
@@ -216,7 +216,7 @@ SpringBootAI 是一个采用 Spring 风格注解和分层结构的 Python 应用
216
216
  | AI 与编排 | 模型调用、Tools、RAG、Chain、状态图、MCP client/server | LangChain / LangGraph / 官方 MCP SDK |
217
217
  | 生产治理 | 健康检查、Prometheus、限流熔断、追踪、Swagger | prometheus-client / OpenTelemetry / OpenAPI |
218
218
 
219
- 当前版本是 `2.3.8`;支持 Python 3.10、3.11 和 3.12,许可证为 MIT。项目仍标记为 Beta。用于公网高并发、合规敏感或支付/订单/库存等核心系统前,必须完成目标数据库、流量模型、故障恢复和安全基线验证。内嵌 Gateway 适合内部路由,不替代公网 Nginx/Kong/WAF;Seata `distributed` 对接官方 TC + TCC 回调;`at` 模式通过 ORM 拦截器自动生成 undo_log 实现自动回滚。
219
+ 当前版本是 `2.3.9`;支持 Python 3.10、3.11 和 3.12,许可证为 MIT。项目仍标记为 Beta。用于公网高并发、合规敏感或支付/订单/库存等核心系统前,必须完成目标数据库、流量模型、故障恢复和安全基线验证。内嵌 Gateway 适合内部路由,不替代公网 Nginx/Kong/WAF;Seata `distributed` 对接官方 TC + TCC 回调;`at` 模式通过 ORM 拦截器自动生成 undo_log 实现自动回滚。
220
220
 
221
221
  [新手指南](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/BEGINNER_GUIDE.md) | [全部文档](https://github.com/YUCONGGEN/springbootAI/tree/master/doc) | [变更日志](https://github.com/YUCONGGEN/springbootAI/blob/master/CHANGELOG.md) | [安全报告](https://github.com/YUCONGGEN/springbootAI/blob/master/SECURITY.md) | [发布检查](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/RELEASE_CHECKLIST.md)
222
222
 
@@ -347,10 +347,10 @@ SpringBootAI 是一个 **Python Web 框架**。它把 Java Spring Boot 的"注
347
347
 
348
348
  | 组件 | 当前版本 |
349
349
  |------|----------|
350
- | `springbootai` 框架 API | 2.3.8 |
351
- | `springbootai.orm.pymybatis` | 2.3.8 |
352
- | `springbootai.ai` AI 模块 | 2.3.8 |
353
- | `springbootai.langchain` LangChain 模块 | 2.3.8 |
350
+ | `springbootai` 框架 API | 2.3.9 |
351
+ | `springbootai.orm.pymybatis` | 2.3.9 |
352
+ | `springbootai.ai` AI 模块 | 2.3.9 |
353
+ | `springbootai.langchain` LangChain 模块 | 2.3.9 |
354
354
  | Python | 3.10+ |
355
355
 
356
356
  ### 1.4 适合什么场景
@@ -937,6 +937,16 @@ class InitService:
937
937
  self.connection.close()
938
938
  ```
939
939
 
940
+ 每个 HTTP 请求都会获得 `X-Request-ID`(可通过
941
+ `server.request-id.header` 修改),该值会写回响应并自动进入框架日志,Feign
942
+ 和 Gateway 也会向下游透传。日志会遮蔽 Bearer Token、API Key、密码、Cookie
943
+ 等常见敏感字段;`logging.diagnose` 默认关闭,避免异常帧局部变量泄密。
944
+
945
+ 声明式 Feign 客户端默认复用连接池,对幂等请求执行有限退避重试,并支持连接/
946
+ 读取超时与响应大小限制。直接读取 RAG 文本文件时建议使用
947
+ `TextReader.from_file(path, max_bytes=...)`,文件不存在或超限会明确失败,不会把
948
+ 错误路径误当成内联文本。
949
+
940
950
  ### 5.7 应用事件
941
951
 
942
952
  ```python
@@ -1895,9 +1905,13 @@ export LOG_DIR=logs
1895
1905
 
1896
1906
  # AI 模块
1897
1907
  export AI_PROVIDER=openai
1898
- export AI_ALLOW_FAKE=true
1908
+ export AI_ALLOW_FAKE=false
1899
1909
  export OPENAI_API_KEY=sk-xxx
1900
1910
  export OPENAI_CHAT_MODEL=gpt-4o-mini
1911
+ export AI_REQUEST_TIMEOUT_SECONDS=60
1912
+ export AI_MAX_OUTPUT_TOKENS=4096
1913
+ export AI_MAX_TOTAL_TOKENS=100000
1914
+ export AI_MAX_TOOL_ITERATIONS=5
1901
1915
  export OLLAMA_BASE_URL=http://localhost:11434
1902
1916
  export OLLAMA_CHAT_MODEL=llama3
1903
1917
 
@@ -54,7 +54,7 @@ SpringBootAI 是一个采用 Spring 风格注解和分层结构的 Python 应用
54
54
  | AI 与编排 | 模型调用、Tools、RAG、Chain、状态图、MCP client/server | LangChain / LangGraph / 官方 MCP SDK |
55
55
  | 生产治理 | 健康检查、Prometheus、限流熔断、追踪、Swagger | prometheus-client / OpenTelemetry / OpenAPI |
56
56
 
57
- 当前版本是 `2.3.8`;支持 Python 3.10、3.11 和 3.12,许可证为 MIT。项目仍标记为 Beta。用于公网高并发、合规敏感或支付/订单/库存等核心系统前,必须完成目标数据库、流量模型、故障恢复和安全基线验证。内嵌 Gateway 适合内部路由,不替代公网 Nginx/Kong/WAF;Seata `distributed` 对接官方 TC + TCC 回调;`at` 模式通过 ORM 拦截器自动生成 undo_log 实现自动回滚。
57
+ 当前版本是 `2.3.9`;支持 Python 3.10、3.11 和 3.12,许可证为 MIT。项目仍标记为 Beta。用于公网高并发、合规敏感或支付/订单/库存等核心系统前,必须完成目标数据库、流量模型、故障恢复和安全基线验证。内嵌 Gateway 适合内部路由,不替代公网 Nginx/Kong/WAF;Seata `distributed` 对接官方 TC + TCC 回调;`at` 模式通过 ORM 拦截器自动生成 undo_log 实现自动回滚。
58
58
 
59
59
  [新手指南](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/BEGINNER_GUIDE.md) | [全部文档](https://github.com/YUCONGGEN/springbootAI/tree/master/doc) | [变更日志](https://github.com/YUCONGGEN/springbootAI/blob/master/CHANGELOG.md) | [安全报告](https://github.com/YUCONGGEN/springbootAI/blob/master/SECURITY.md) | [发布检查](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/RELEASE_CHECKLIST.md)
60
60
 
@@ -185,10 +185,10 @@ SpringBootAI 是一个 **Python Web 框架**。它把 Java Spring Boot 的"注
185
185
 
186
186
  | 组件 | 当前版本 |
187
187
  |------|----------|
188
- | `springbootai` 框架 API | 2.3.8 |
189
- | `springbootai.orm.pymybatis` | 2.3.8 |
190
- | `springbootai.ai` AI 模块 | 2.3.8 |
191
- | `springbootai.langchain` LangChain 模块 | 2.3.8 |
188
+ | `springbootai` 框架 API | 2.3.9 |
189
+ | `springbootai.orm.pymybatis` | 2.3.9 |
190
+ | `springbootai.ai` AI 模块 | 2.3.9 |
191
+ | `springbootai.langchain` LangChain 模块 | 2.3.9 |
192
192
  | Python | 3.10+ |
193
193
 
194
194
  ### 1.4 适合什么场景
@@ -775,6 +775,16 @@ class InitService:
775
775
  self.connection.close()
776
776
  ```
777
777
 
778
+ 每个 HTTP 请求都会获得 `X-Request-ID`(可通过
779
+ `server.request-id.header` 修改),该值会写回响应并自动进入框架日志,Feign
780
+ 和 Gateway 也会向下游透传。日志会遮蔽 Bearer Token、API Key、密码、Cookie
781
+ 等常见敏感字段;`logging.diagnose` 默认关闭,避免异常帧局部变量泄密。
782
+
783
+ 声明式 Feign 客户端默认复用连接池,对幂等请求执行有限退避重试,并支持连接/
784
+ 读取超时与响应大小限制。直接读取 RAG 文本文件时建议使用
785
+ `TextReader.from_file(path, max_bytes=...)`,文件不存在或超限会明确失败,不会把
786
+ 错误路径误当成内联文本。
787
+
778
788
  ### 5.7 应用事件
779
789
 
780
790
  ```python
@@ -1733,9 +1743,13 @@ export LOG_DIR=logs
1733
1743
 
1734
1744
  # AI 模块
1735
1745
  export AI_PROVIDER=openai
1736
- export AI_ALLOW_FAKE=true
1746
+ export AI_ALLOW_FAKE=false
1737
1747
  export OPENAI_API_KEY=sk-xxx
1738
1748
  export OPENAI_CHAT_MODEL=gpt-4o-mini
1749
+ export AI_REQUEST_TIMEOUT_SECONDS=60
1750
+ export AI_MAX_OUTPUT_TOKENS=4096
1751
+ export AI_MAX_TOTAL_TOKENS=100000
1752
+ export AI_MAX_TOOL_ITERATIONS=5
1739
1753
  export OLLAMA_BASE_URL=http://localhost:11434
1740
1754
  export OLLAMA_CHAT_MODEL=llama3
1741
1755
 
@@ -12,7 +12,7 @@ build-backend = "setuptools.build_meta"
12
12
  [project]
13
13
  # Distribution name: springbootAI (pip install springbootAI); import package: springbootai.
14
14
  name = "springbootAI"
15
- version = "2.3.8"
15
+ version = "2.3.9"
16
16
  description = "Spring-style Python framework with Web, ORM, Cloud and AI integrations"
17
17
  readme = "README.md"
18
18
  license = "MIT"
@@ -256,6 +256,7 @@ full = [
256
256
 
257
257
  [tool.pytest.ini_options]
258
258
  pythonpath = [".", "examples"]
259
+ testpaths = ["tests"]
259
260
  filterwarnings = [
260
261
  # 闈欓粯 langchain_classic 寮冪敤鍛婅鍜?community sunset 鍛婅
261
262
  # 鍘熷洜锛氭湰椤圭洰鏈夋剰閿佸畾 langchain classic (1.x) API锛岃繖浜涙槸棰勬湡鍐呯殑妗嗘灦绾у憡璀?
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: springbootAI
3
- Version: 2.3.8
3
+ Version: 2.3.9
4
4
  Summary: Spring-style Python framework with Web, ORM, Cloud and AI integrations
5
5
  Author-email: YuConggen <1516933915@qq.com>
6
6
  License-Expression: MIT
@@ -216,7 +216,7 @@ SpringBootAI 是一个采用 Spring 风格注解和分层结构的 Python 应用
216
216
  | AI 与编排 | 模型调用、Tools、RAG、Chain、状态图、MCP client/server | LangChain / LangGraph / 官方 MCP SDK |
217
217
  | 生产治理 | 健康检查、Prometheus、限流熔断、追踪、Swagger | prometheus-client / OpenTelemetry / OpenAPI |
218
218
 
219
- 当前版本是 `2.3.8`;支持 Python 3.10、3.11 和 3.12,许可证为 MIT。项目仍标记为 Beta。用于公网高并发、合规敏感或支付/订单/库存等核心系统前,必须完成目标数据库、流量模型、故障恢复和安全基线验证。内嵌 Gateway 适合内部路由,不替代公网 Nginx/Kong/WAF;Seata `distributed` 对接官方 TC + TCC 回调;`at` 模式通过 ORM 拦截器自动生成 undo_log 实现自动回滚。
219
+ 当前版本是 `2.3.9`;支持 Python 3.10、3.11 和 3.12,许可证为 MIT。项目仍标记为 Beta。用于公网高并发、合规敏感或支付/订单/库存等核心系统前,必须完成目标数据库、流量模型、故障恢复和安全基线验证。内嵌 Gateway 适合内部路由,不替代公网 Nginx/Kong/WAF;Seata `distributed` 对接官方 TC + TCC 回调;`at` 模式通过 ORM 拦截器自动生成 undo_log 实现自动回滚。
220
220
 
221
221
  [新手指南](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/BEGINNER_GUIDE.md) | [全部文档](https://github.com/YUCONGGEN/springbootAI/tree/master/doc) | [变更日志](https://github.com/YUCONGGEN/springbootAI/blob/master/CHANGELOG.md) | [安全报告](https://github.com/YUCONGGEN/springbootAI/blob/master/SECURITY.md) | [发布检查](https://github.com/YUCONGGEN/springbootAI/blob/master/doc/RELEASE_CHECKLIST.md)
222
222
 
@@ -347,10 +347,10 @@ SpringBootAI 是一个 **Python Web 框架**。它把 Java Spring Boot 的"注
347
347
 
348
348
  | 组件 | 当前版本 |
349
349
  |------|----------|
350
- | `springbootai` 框架 API | 2.3.8 |
351
- | `springbootai.orm.pymybatis` | 2.3.8 |
352
- | `springbootai.ai` AI 模块 | 2.3.8 |
353
- | `springbootai.langchain` LangChain 模块 | 2.3.8 |
350
+ | `springbootai` 框架 API | 2.3.9 |
351
+ | `springbootai.orm.pymybatis` | 2.3.9 |
352
+ | `springbootai.ai` AI 模块 | 2.3.9 |
353
+ | `springbootai.langchain` LangChain 模块 | 2.3.9 |
354
354
  | Python | 3.10+ |
355
355
 
356
356
  ### 1.4 适合什么场景
@@ -937,6 +937,16 @@ class InitService:
937
937
  self.connection.close()
938
938
  ```
939
939
 
940
+ 每个 HTTP 请求都会获得 `X-Request-ID`(可通过
941
+ `server.request-id.header` 修改),该值会写回响应并自动进入框架日志,Feign
942
+ 和 Gateway 也会向下游透传。日志会遮蔽 Bearer Token、API Key、密码、Cookie
943
+ 等常见敏感字段;`logging.diagnose` 默认关闭,避免异常帧局部变量泄密。
944
+
945
+ 声明式 Feign 客户端默认复用连接池,对幂等请求执行有限退避重试,并支持连接/
946
+ 读取超时与响应大小限制。直接读取 RAG 文本文件时建议使用
947
+ `TextReader.from_file(path, max_bytes=...)`,文件不存在或超限会明确失败,不会把
948
+ 错误路径误当成内联文本。
949
+
940
950
  ### 5.7 应用事件
941
951
 
942
952
  ```python
@@ -1895,9 +1905,13 @@ export LOG_DIR=logs
1895
1905
 
1896
1906
  # AI 模块
1897
1907
  export AI_PROVIDER=openai
1898
- export AI_ALLOW_FAKE=true
1908
+ export AI_ALLOW_FAKE=false
1899
1909
  export OPENAI_API_KEY=sk-xxx
1900
1910
  export OPENAI_CHAT_MODEL=gpt-4o-mini
1911
+ export AI_REQUEST_TIMEOUT_SECONDS=60
1912
+ export AI_MAX_OUTPUT_TOKENS=4096
1913
+ export AI_MAX_TOTAL_TOKENS=100000
1914
+ export AI_MAX_TOOL_ITERATIONS=5
1901
1915
  export OLLAMA_BASE_URL=http://localhost:11434
1902
1916
  export OLLAMA_CHAT_MODEL=llama3
1903
1917
 
@@ -157,6 +157,7 @@ springbootai/langgraph/checkpoint.py
157
157
  springbootai/langgraph/config.py
158
158
  springbootai/langgraph/runtime.py
159
159
  springbootai/logging/__init__.py
160
+ springbootai/logging/context.py
160
161
  springbootai/logging/loguru_logger.py
161
162
  springbootai/mcp/__init__.py
162
163
  springbootai/mcp/annotation_runtime.py
@@ -266,7 +267,9 @@ tests/test_actuator_prometheus_admin.py
266
267
  tests/test_ai_annotations.py
267
268
  tests/test_ai_comprehensive.py
268
269
  tests/test_ai_declarative_annotations.py
270
+ tests/test_ai_enterprise_hardening.py
269
271
  tests/test_ai_module.py
272
+ tests/test_ai_stream_hardening.py
270
273
  tests/test_annotation_combinations.py
271
274
  tests/test_annotations_contract.py
272
275
  tests/test_aop_annotations_full.py
@@ -278,9 +281,11 @@ tests/test_bus.py
278
281
  tests/test_cache_annotations.py
279
282
  tests/test_cli.py
280
283
  tests/test_cloud_embedded_full.py
284
+ tests/test_cloud_log_safety.py
281
285
  tests/test_component_init_error.py
282
286
  tests/test_compositional_annotations.py
283
287
  tests/test_conditional_annotations.py
288
+ tests/test_config_admin_hardening.py
284
289
  tests/test_config_binding.py
285
290
  tests/test_config_center.py
286
291
  tests/test_config_center_hardening.py
@@ -297,10 +302,12 @@ tests/test_datasource_routing.py
297
302
  tests/test_ddl_auto.py
298
303
  tests/test_declarative_aop_post_authorize_recover.py
299
304
  tests/test_devtools.py
305
+ tests/test_devtools_lifecycle_hardening.py
300
306
  tests/test_di_config_event_full.py
301
307
  tests/test_excel_module.py
302
308
  tests/test_hateoas.py
303
309
  tests/test_i18n_module.py
310
+ tests/test_io_http_logging_hardening.py
304
311
  tests/test_ioc_lifecycle_enhancements.py
305
312
  tests/test_jpa_version_transient.py
306
313
  tests/test_kafka.py
@@ -19,7 +19,7 @@ from .config import *
19
19
  from .utils import *
20
20
  from .main import create_app, run, SpringApplication, run_cli
21
21
 
22
- __version__ = "2.3.8"
22
+ __version__ = "2.3.9"
23
23
  __author__ = "yuconggen"
24
24
  __license__ = "MIT"
25
25
 
@@ -16,7 +16,7 @@ SpringBootAI AI 模块 - 对齐 Spring AI 的 ChatClient/Advisor/ETL 抽象,
16
16
  from springbootai.ai.core import (
17
17
  Advisor, AdvisorRequest, ChatClient, ChatClientBuilder, ChatModel,
18
18
  ChatResponse, EmbeddingModel, Generation, Message, MessageType,
19
- PromptSpec,
19
+ PromptSpec, TokenBudgetExceededError, ToolLoopLimitExceededError,
20
20
  )
21
21
  from springbootai.ai.annotations import (
22
22
  Agent, AiAdvisor, AiCache, AiClient, AiMemory, AiRetry, ContentModeration,
@@ -34,7 +34,8 @@ from springbootai.ai.vectorstore import (
34
34
  SearchRequest, SimpleInMemoryVectorStore, VectorStore, cosine_similarity,
35
35
  )
36
36
  from springbootai.ai.etl import (
37
- CharacterTextSplitter, DocumentReader, TextDocument, TextReader,
37
+ CharacterTextSplitter, DocumentReader, DocumentTooLargeError,
38
+ TextDocument, TextReader,
38
39
  TextSplitter, TokenTextSplitter,
39
40
  )
40
41
  from springbootai.ai.tools import (
@@ -42,10 +43,12 @@ from springbootai.ai.tools import (
42
43
  ToolDefinition,
43
44
  ToolExecutionPolicy,
44
45
  ToolRegistry,
46
+ ToolCancellationToken,
45
47
  )
46
48
  from springbootai.ai.providers import (
47
49
  FakeChatModel, FakeEmbeddingModel, OllamaChatModel, OllamaEmbeddingModel,
48
50
  OpenAICompatChatModel, OpenAIChatModel, OpenAIEmbeddingModel,
51
+ ProviderProtocolError, ProviderResponseTooLargeError, ProviderStreamError,
49
52
  )
50
53
  from springbootai.ai.resilience import (
51
54
  AICircuitBreaker, CircuitOpenError, TransientError, resilient_call,
@@ -54,13 +57,14 @@ from springbootai.ai.observability import AIMetrics, ai_metrics
54
57
  from springbootai.ai.autoconfig import AIProperties, bind_ai_config, configure_ai
55
58
  from springbootai.ai.annotation_runtime import ContentModerationError
56
59
 
57
- __version__ = "2.3.8"
60
+ __version__ = "2.3.9"
58
61
 
59
62
  __all__ = [
60
63
  # core
61
64
  "Advisor", "AdvisorRequest", "ChatClient", "ChatClientBuilder",
62
65
  "ChatModel", "ChatResponse", "EmbeddingModel", "Generation", "Message",
63
- "MessageType", "PromptSpec",
66
+ "MessageType", "PromptSpec", "TokenBudgetExceededError",
67
+ "ToolLoopLimitExceededError",
64
68
  # annotations
65
69
  "AiAdvisor", "AiClient", "AiMemory", "Tool", "Prompt", "RAG",
66
70
  "StructuredOutput", "Agent", "Embedding", "VectorStore", "AiRetry",
@@ -76,14 +80,18 @@ __all__ = [
76
80
  "SearchRequest", "SimpleInMemoryVectorStore", "VectorStore",
77
81
  "cosine_similarity",
78
82
  # etl
79
- "CharacterTextSplitter", "DocumentReader", "TextDocument", "TextReader",
83
+ "CharacterTextSplitter", "DocumentReader", "DocumentTooLargeError",
84
+ "TextDocument", "TextReader",
80
85
  "TextSplitter", "TokenTextSplitter",
81
86
  # tools
82
- "CompositeToolRegistry", "ToolDefinition", "ToolExecutionPolicy", "ToolRegistry",
87
+ "CompositeToolRegistry", "ToolCancellationToken", "ToolDefinition",
88
+ "ToolExecutionPolicy", "ToolRegistry",
83
89
  # providers
84
90
  "FakeChatModel", "FakeEmbeddingModel", "OllamaChatModel",
85
91
  "OllamaEmbeddingModel", "OpenAICompatChatModel", "OpenAIChatModel",
86
- "OpenAIEmbeddingModel",
92
+ "OpenAIEmbeddingModel", "ProviderProtocolError",
93
+ "ProviderResponseTooLargeError",
94
+ "ProviderStreamError",
87
95
  # resilience
88
96
  "AICircuitBreaker", "CircuitOpenError", "TransientError", "resilient_call",
89
97
  # observability
@@ -1,7 +1,9 @@
1
1
  """
2
2
  Advisor 实现 - QuestionAnswerAdvisor(RAG)与 MessageChatMemoryAdvisor(会话记忆)。
3
3
  """
4
- from typing import Any, Dict, List
4
+ import inspect
5
+ from urllib.parse import quote
6
+ from typing import Any, Dict, List, Optional, Sequence
5
7
 
6
8
  from springbootai.ai.core import (
7
9
  Advisor, AdvisorRequest, ChatResponse, Message, MessageType,
@@ -25,11 +27,31 @@ class MessageChatMemoryAdvisor(Advisor):
25
27
 
26
28
  @staticmethod
27
29
  def _build_namespace(context: dict) -> str:
28
- tenant = str(context.get("tenant_id", "")).strip()
29
- user = str(context.get("user_id", "")).strip()
30
+ tenant = quote(str(context.get("tenant_id", "")).strip()[:128], safe="-_.~")
31
+ user = quote(str(context.get("user_id", "")).strip()[:128], safe="-_.~")
30
32
  parts = [p for p in (tenant, user) if p]
31
33
  return ":".join(parts) if parts else ""
32
34
 
35
+ @staticmethod
36
+ def _call_memory(method, *args, namespace: str, **kwargs):
37
+ """Call new namespaced memory APIs without silently weakening old backends."""
38
+ try:
39
+ parameters = inspect.signature(method).parameters.values()
40
+ supports_namespace = any(
41
+ p.name == "namespace" or p.kind == inspect.Parameter.VAR_KEYWORD
42
+ for p in parameters
43
+ )
44
+ except (TypeError, ValueError):
45
+ supports_namespace = False
46
+ if namespace and not supports_namespace:
47
+ raise RuntimeError(
48
+ "ChatMemory backend does not support request-scoped namespaces; "
49
+ "refusing a potentially cross-tenant memory access"
50
+ )
51
+ if supports_namespace:
52
+ kwargs["namespace"] = namespace
53
+ return method(*args, **kwargs)
54
+
33
55
  def __init__(self, memory: ChatMemory, max_messages: int = 20):
34
56
  self.memory = memory
35
57
  self.max_messages = max_messages
@@ -44,12 +66,15 @@ class MessageChatMemoryAdvisor(Advisor):
44
66
  "跳过历史注入。请在上游设置 request.context['conversation_id']。")
45
67
  return request
46
68
 
47
- # 如果 memory 支持 namespace 则注入用户/租户上下文
69
+ # Namespace is passed per operation. Never mutate a shared memory bean:
70
+ # concurrent requests may belong to different tenants.
48
71
  ns = self._build_namespace(request.context)
49
- if ns and hasattr(self.memory, "_namespace"):
50
- self.memory._namespace = ns
72
+ request.context["memory_namespace"] = ns
51
73
 
52
- history = self.memory.get(str(conv_id), last_n=self.max_messages)
74
+ history = self._call_memory(
75
+ self.memory.get, str(conv_id), last_n=self.max_messages,
76
+ namespace=ns,
77
+ )
53
78
  # 历史 + 本次输入合并
54
79
  request.messages = history + request.messages
55
80
  return request
@@ -59,14 +84,18 @@ class MessageChatMemoryAdvisor(Advisor):
59
84
  conv_id = request.context.get("conversation_id")
60
85
  if not conv_id:
61
86
  return response
87
+ ns = str(request.context.get("memory_namespace") or
88
+ self._build_namespace(request.context))
62
89
  # 保存用户输入(最后一条 user 消息)
63
90
  for msg in reversed(request.messages):
64
91
  if msg.type == MessageType.USER:
65
- self.memory.add(conv_id, msg)
92
+ self._call_memory(
93
+ self.memory.add, str(conv_id), msg, namespace=ns)
66
94
  break
67
95
  # 保存模型回复
68
96
  if response.output:
69
- self.memory.add(conv_id, response.output)
97
+ self._call_memory(
98
+ self.memory.add, str(conv_id), response.output, namespace=ns)
70
99
  return response
71
100
 
72
101
 
@@ -89,12 +118,16 @@ class QuestionAnswerAdvisor(Advisor):
89
118
  prompt_template: str = "",
90
119
  top_k: int = 4,
91
120
  embedding_model=None,
92
- harden_injection: bool = True):
121
+ harden_injection: bool = True,
122
+ filter_metadata: Optional[Dict[str, Any]] = None,
123
+ filter_context_keys: Sequence[str] = ("tenant_id",)):
93
124
  self.vector_store = vector_store
94
125
  self.prompt_template = prompt_template or self.DEFAULT_PROMPT_TEMPLATE
95
126
  self.top_k = top_k
96
127
  self.embedding_model = embedding_model
97
128
  self.harden_injection = harden_injection
129
+ self.filter_metadata = dict(filter_metadata or {})
130
+ self.filter_context_keys = tuple(filter_context_keys)
98
131
 
99
132
  def advise_request(self, request: AdvisorRequest) -> AdvisorRequest:
100
133
  # 取最后一条用户消息作为查询
@@ -110,9 +143,21 @@ class QuestionAnswerAdvisor(Advisor):
110
143
  emb = None
111
144
  if self.embedding_model:
112
145
  emb = self.embedding_model.embed_one(query)
146
+ filters = dict(self.filter_metadata)
147
+ for key in self.filter_context_keys:
148
+ value = request.context.get(key)
149
+ if value is not None and str(value).strip():
150
+ filters[key] = str(value).strip()
151
+ # When no tenant exists, a verified user identity can still isolate a
152
+ # personal knowledge base. Tenant scope takes precedence by default so
153
+ # shared tenant documents do not require a redundant user_id field.
154
+ if not filters and request.context.get("user_id"):
155
+ filters["user_id"] = str(request.context["user_id"]).strip()
156
+
113
157
  search_req = SearchRequest(
114
158
  query=query, embedding=emb, top_k=self.top_k,
115
159
  similarity_threshold=0.1,
160
+ filter_metadata=filters or None,
116
161
  )
117
162
  docs = self.vector_store.similarity_search(search_req)
118
163
  if not docs:
@@ -15,7 +15,7 @@ import os
15
15
  import threading
16
16
  import time
17
17
  from collections import OrderedDict
18
- from typing import Any, Callable, Iterable
18
+ from typing import Any, Callable, Optional
19
19
 
20
20
  from springbootai.ai.annotations import (
21
21
  Agent, AiCache, AiRetry, ContentModeration, Embedding, Prompt, RAG,
@@ -449,10 +449,15 @@ def _invoke_chat(factory: Any, annotation: Prompt, query: str, values: dict[str,
449
449
  system = _render(annotation.system, values)
450
450
  if system:
451
451
  spec.system(system)
452
- return spec.user(query).call()
452
+ spec.user(query)
453
+ for key in ("tenant_id", "user_id", "conversation_id"):
454
+ if values.get(key) is not None:
455
+ spec.param(key, values[key])
456
+ return spec.call()
453
457
 
454
458
 
455
- def _invoke_rag(factory: Any, annotation: RAG, query: str) -> Any:
459
+ def _invoke_rag(factory: Any, annotation: RAG, query: str,
460
+ values: Optional[dict[str, Any]] = None) -> Any:
456
461
  client = _resolve(factory, annotation.client)
457
462
  store = _resolve(factory, annotation.vector_store)
458
463
  embedding = _resolve(factory, annotation.embedding)
@@ -463,7 +468,14 @@ def _invoke_rag(factory: Any, annotation: RAG, query: str) -> Any:
463
468
  store, prompt_template=annotation.prompt_template,
464
469
  top_k=annotation.top_k, embedding_model=embedding,
465
470
  )
466
- return client.prompt().advisors(advisor).user(query).call()
471
+ spec = client.prompt().advisors(advisor).user(query)
472
+ # Carry only identity/session fields into AdvisorRequest. Arbitrary method
473
+ # arguments must never become trusted authorization context implicitly.
474
+ values = values or {}
475
+ for key in ("tenant_id", "user_id", "conversation_id"):
476
+ if values.get(key) is not None:
477
+ spec.param(key, values[key])
478
+ return spec.call()
467
479
 
468
480
 
469
481
  def _invoke_agent(factory: Any, annotation: Agent, query: str) -> Any:
@@ -508,7 +520,7 @@ def apply_ai_annotations(factory: Any, instance: Any, method: Callable) -> Calla
508
520
  if query is None:
509
521
  original = method(*args, **kwargs)
510
522
  query = _content(original)
511
- result = _invoke_rag(factory, rag_ann, query)
523
+ result = _invoke_rag(factory, rag_ann, query, values)
512
524
  elif agent_ann:
513
525
  original = method(*args, **kwargs)
514
526
  result = _invoke_agent(factory, agent_ann, _content(original))
@@ -545,7 +557,7 @@ def apply_ai_annotations(factory: Any, instance: Any, method: Callable) -> Calla
545
557
  result = _invoke_chat(factory, prompt_ann, _render(prompt_ann.template, values), values)
546
558
  elif rag_ann:
547
559
  original = await method(*args, **kwargs)
548
- result = _invoke_rag(factory, rag_ann, _content(original))
560
+ result = _invoke_rag(factory, rag_ann, _content(original), values)
549
561
  elif agent_ann:
550
562
  original = await method(*args, **kwargs)
551
563
  result = _invoke_agent(factory, agent_ann, _content(original))