ErisPulse 2.6.2__tar.gz → 2.6.3.dev0__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 (196) hide show
  1. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/PKG-INFO +1 -1
  2. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/pyproject.toml +1 -1
  3. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/__init__.py +2 -1
  4. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/__init__.pyi +1 -1
  5. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/client.py +7 -0
  6. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/errors.py +11 -0
  7. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/kv_builder.py +5 -0
  8. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/router.py +7 -0
  9. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/send_builder.py +6 -0
  10. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/send_rules.py +6 -0
  11. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/websocket.py +6 -0
  12. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/adapter.py +94 -0
  13. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/client.py +7 -0
  14. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/config.py +7 -0
  15. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/constants.py +103 -0
  16. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/en.py +2 -0
  17. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/ja.py +2 -0
  18. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/ru.py +2 -0
  19. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/zh_cn.py +2 -0
  20. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/zh_tw.py +2 -0
  21. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/master.py +5 -0
  22. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/module.py +96 -0
  23. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/__init__.py +15 -0
  24. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/.gitignore +0 -0
  25. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/LICENSE +0 -0
  26. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/README.pypi.md +0 -0
  27. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/__init__.py +0 -0
  28. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/__init__.pyi +0 -0
  29. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/base.py +0 -0
  30. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/base.pyi +0 -0
  31. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/cli.py +0 -0
  32. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/cli.pyi +0 -0
  33. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/__init__.py +0 -0
  34. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/__init__.pyi +0 -0
  35. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/create.py +0 -0
  36. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/create.pyi +0 -0
  37. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/init.py +0 -0
  38. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/init.pyi +0 -0
  39. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/install.py +0 -0
  40. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/install.pyi +0 -0
  41. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/language.py +0 -0
  42. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/language.pyi +0 -0
  43. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/list.py +0 -0
  44. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/list.pyi +0 -0
  45. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/list_remote.py +0 -0
  46. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/list_remote.pyi +0 -0
  47. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/run.py +0 -0
  48. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/run.pyi +0 -0
  49. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/self_update.py +0 -0
  50. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/self_update.pyi +0 -0
  51. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/types.py +0 -0
  52. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/types.pyi +0 -0
  53. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/uninstall.py +0 -0
  54. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/uninstall.pyi +0 -0
  55. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/upgrade.py +0 -0
  56. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/upgrade.pyi +0 -0
  57. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/console.py +0 -0
  58. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/console.pyi +0 -0
  59. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/hints.py +0 -0
  60. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/hints.pyi +0 -0
  61. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/__init__.py +0 -0
  62. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/__init__.pyi +0 -0
  63. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/__init__.py +0 -0
  64. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/__init__.pyi +0 -0
  65. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/en.py +0 -0
  66. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/en.pyi +0 -0
  67. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/ja.py +0 -0
  68. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/ja.pyi +0 -0
  69. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/ru.py +0 -0
  70. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/ru.pyi +0 -0
  71. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/zh_cn.py +0 -0
  72. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/zh_cn.pyi +0 -0
  73. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/zh_tw.py +0 -0
  74. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/zh_tw.pyi +0 -0
  75. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/registry.py +0 -0
  76. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/registry.pyi +0 -0
  77. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/utils/__init__.py +0 -0
  78. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/utils/__init__.pyi +0 -0
  79. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/utils/display.py +0 -0
  80. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/utils/display.pyi +0 -0
  81. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/utils/file_watcher.py +0 -0
  82. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/utils/file_watcher.pyi +0 -0
  83. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/utils/package_manager.py +0 -0
  84. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/utils/package_manager.pyi +0 -0
  85. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/adapter.py +0 -0
  86. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/adapter.pyi +0 -0
  87. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/client.pyi +0 -0
  88. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/errors.pyi +0 -0
  89. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/kv_builder.pyi +0 -0
  90. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/manager.py +0 -0
  91. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/manager.pyi +0 -0
  92. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/module.py +0 -0
  93. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/module.pyi +0 -0
  94. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/router.pyi +0 -0
  95. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/send_builder.pyi +0 -0
  96. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/send_rules.pyi +0 -0
  97. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/storage.py +0 -0
  98. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/storage.pyi +0 -0
  99. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/websocket.pyi +0 -0
  100. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/__init__.py +0 -0
  101. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/__init__.pyi +0 -0
  102. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/base.py +0 -0
  103. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/base.pyi +0 -0
  104. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/command.py +0 -0
  105. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/command.pyi +0 -0
  106. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/message.py +0 -0
  107. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/message.pyi +0 -0
  108. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/message_builder.py +0 -0
  109. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/message_builder.pyi +0 -0
  110. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/meta.py +0 -0
  111. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/meta.pyi +0 -0
  112. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/notice.py +0 -0
  113. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/notice.pyi +0 -0
  114. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/request.py +0 -0
  115. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/request.pyi +0 -0
  116. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/session_type.py +0 -0
  117. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/session_type.pyi +0 -0
  118. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/wrapper.py +0 -0
  119. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/wrapper.pyi +0 -0
  120. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/__init__.py +0 -0
  121. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/__init__.pyi +0 -0
  122. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/adapter.pyi +0 -0
  123. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/assets/__init__.py +0 -0
  124. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/assets/__init__.pyi +0 -0
  125. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/assets/error.css +0 -0
  126. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/assets/error.html +0 -0
  127. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/assets/root.css +0 -0
  128. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/assets/root.html +0 -0
  129. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/client.pyi +0 -0
  130. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/config.pyi +0 -0
  131. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/constants.pyi +0 -0
  132. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/__init__.py +0 -0
  133. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/__init__.pyi +0 -0
  134. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/constants.py +0 -0
  135. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/constants.pyi +0 -0
  136. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/__init__.py +0 -0
  137. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/__init__.pyi +0 -0
  138. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/en.pyi +0 -0
  139. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/ja.pyi +0 -0
  140. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/ru.pyi +0 -0
  141. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/zh_cn.pyi +0 -0
  142. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/zh_tw.pyi +0 -0
  143. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/lifecycle.py +0 -0
  144. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/lifecycle.pyi +0 -0
  145. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/logger.py +0 -0
  146. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/logger.pyi +0 -0
  147. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/master.pyi +0 -0
  148. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/module.pyi +0 -0
  149. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/router.py +0 -0
  150. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/router.pyi +0 -0
  151. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/storage.py +0 -0
  152. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/storage.pyi +0 -0
  153. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/__init__.pyi +0 -0
  154. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/__main__.py +0 -0
  155. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/__main__.pyi +0 -0
  156. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/__init__.py +0 -0
  157. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/__init__.pyi +0 -0
  158. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/adapter.py +0 -0
  159. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/adapter.pyi +0 -0
  160. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/bases/__init__.py +0 -0
  161. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/bases/__init__.pyi +0 -0
  162. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/bases/finder.py +0 -0
  163. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/bases/finder.pyi +0 -0
  164. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/module.py +0 -0
  165. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/module.pyi +0 -0
  166. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/__init__.py +0 -0
  167. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/__init__.pyi +0 -0
  168. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/adapter.py +0 -0
  169. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/adapter.pyi +0 -0
  170. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/bases/__init__.py +0 -0
  171. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/bases/__init__.pyi +0 -0
  172. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/bases/loader.py +0 -0
  173. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/bases/loader.pyi +0 -0
  174. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/module.py +0 -0
  175. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/module.pyi +0 -0
  176. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/strategy.py +0 -0
  177. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/strategy.pyi +0 -0
  178. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/strict.py +0 -0
  179. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/strict.pyi +0 -0
  180. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/py.typed +0 -0
  181. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/__init__.py +0 -0
  182. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/__init__.pyi +0 -0
  183. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/config_schema.py +0 -0
  184. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/config_schema.pyi +0 -0
  185. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/context.py +0 -0
  186. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/context.pyi +0 -0
  187. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/exceptions.py +0 -0
  188. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/exceptions.pyi +0 -0
  189. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/frame_config.py +0 -0
  190. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/frame_config.pyi +0 -0
  191. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/hints.py +0 -0
  192. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/hints.pyi +0 -0
  193. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/tasks.py +0 -0
  194. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/tasks.pyi +0 -0
  195. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/sdk.py +0 -0
  196. {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/sdk.pyi +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ErisPulse
3
- Version: 2.6.2
3
+ Version: 2.6.3.dev0
4
4
  Summary: Event-driven modular async bot framework — write once, deploy to any platform | 事件驱动的模块化异步机器人框架,一次编写,多平台部署
5
5
  Project-URL: Homepage, https://github.com/ErisPulse/ErisPulse
6
6
  Project-URL: Documentation, https://www.erisdev.com#docs
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "ErisPulse"
7
- version = "2.6.2"
7
+ version = "2.6.3-dev.0"
8
8
  description = "Event-driven modular async bot framework — write once, deploy to any platform | 事件驱动的模块化异步机器人框架,一次编写,多平台部署"
9
9
  readme = "README.pypi.md"
10
10
  requires-python = ">=3.10"
@@ -20,7 +20,7 @@ from .errors import (
20
20
  WebSocketDisconnect,
21
21
  )
22
22
  from .websocket import WebSocketConnectionBase, WSMessage
23
- from .router import HttpRequest, WebSocketConnection
23
+ from .router import HttpRequest, WebSocketConnection, SseEmitter
24
24
  from .client import BaseHttpClient, BaseHttpResponse, BaseClientWebSocket
25
25
 
26
26
  __all__ = [
@@ -43,6 +43,7 @@ __all__ = [
43
43
  "SendBuilder",
44
44
  "SendContext",
45
45
  "SendDSL",
46
+ "SseEmitter",
46
47
  "WSMessage",
47
48
  "WebSocketConnection",
48
49
  "WebSocketConnectionBase",
@@ -15,5 +15,5 @@ from .storage import BaseStorage, BaseQueryBuilder
15
15
  from .kv_builder import KVQueryBuilder
16
16
  from .errors import ErisPulseError, ClientError, ClientConnectionError, ClientTimeoutError, HTTPStatusError, WebSocketError, WebSocketDisconnect
17
17
  from .websocket import WebSocketConnectionBase, WSMessage
18
- from .router import HttpRequest, WebSocketConnection
18
+ from .router import HttpRequest, WebSocketConnection, SseEmitter
19
19
  from .client import BaseHttpClient, BaseHttpResponse, BaseClientWebSocket
@@ -330,3 +330,10 @@ class BaseHttpClient:
330
330
  重置统计数据
331
331
  """
332
332
  raise NotImplementedError
333
+
334
+
335
+ __all__ = [
336
+ "BaseClientWebSocket",
337
+ "BaseHttpClient",
338
+ "BaseHttpResponse",
339
+ ]
@@ -129,3 +129,14 @@ class WebSocketDisconnect(WebSocketError):
129
129
  self.code = code
130
130
  self.reason = reason or ""
131
131
  super().__init__(f"code={self.code}, reason={self.reason}")
132
+
133
+
134
+ __all__ = [
135
+ "ClientConnectionError",
136
+ "ClientError",
137
+ "ClientTimeoutError",
138
+ "ErisPulseError",
139
+ "HTTPStatusError",
140
+ "WebSocketDisconnect",
141
+ "WebSocketError",
142
+ ]
@@ -373,3 +373,8 @@ class KVQueryBuilder(BaseQueryBuilder):
373
373
 
374
374
  async def aExists(self) -> bool:
375
375
  return await self.aCount() > 0
376
+
377
+
378
+ __all__ = [
379
+ "KVQueryBuilder",
380
+ ]
@@ -628,3 +628,10 @@ class SseEmitter:
628
628
  self._closed = True
629
629
  if self._on_close is not None:
630
630
  await self._on_close()
631
+
632
+
633
+ __all__ = [
634
+ "HttpRequest",
635
+ "SseEmitter",
636
+ "WebSocketConnection",
637
+ ]
@@ -465,3 +465,9 @@ class SendBuilder:
465
465
  except Exception:
466
466
  # 生命周期事件失败不应影响批量发送
467
467
  pass
468
+
469
+
470
+ __all__ = [
471
+ "BatchContext",
472
+ "SendBuilder",
473
+ ]
@@ -333,3 +333,9 @@ class _PriorityQueue:
333
333
  def reset(cls) -> None:
334
334
  """重置状态(主要用于测试)"""
335
335
  cls._inflight = 0
336
+
337
+
338
+ __all__ = [
339
+ "SendContext",
340
+ "apply_send_rules",
341
+ ]
@@ -263,3 +263,9 @@ class WebSocketConnectionBase:
263
263
  return func
264
264
 
265
265
  return decorator
266
+
267
+
268
+ __all__ = [
269
+ "WSMessage",
270
+ "WebSocketConnectionBase",
271
+ ]
@@ -138,6 +138,9 @@ class AdapterManager(ManagerBase):
138
138
  # 标记是否正在关闭,避免重复提交离线事件
139
139
  self._is_being_shutdown = False
140
140
 
141
+ # 注册配置变更路由:将 config.set / config.updated 事件转发到各适配器的 on_config_update
142
+ self._register_config_change_routing()
143
+
141
144
  def set_sdk_ref(self, sdk) -> bool:
142
145
  """
143
146
  设置 SDK 引用
@@ -152,6 +155,97 @@ class AdapterManager(ManagerBase):
152
155
  logger.error(i18n.t("core.adapter.set_sdk_failed", error=e))
153
156
  return False
154
157
 
158
+ # ==================== 配置变更路由 ====================
159
+
160
+ def _register_config_change_routing(self) -> None:
161
+ """
162
+ {!--< internal-use >!--}
163
+ 注册 config.set / config.updated 事件订阅,将配置变更路由到各适配器的 on_config_update
164
+ """
165
+ lifecycle.register("config.set", self._on_config_set)
166
+ lifecycle.register("config.updated", self._on_config_updated)
167
+
168
+ def _on_config_set(self, data: dict) -> None:
169
+ """
170
+ {!--< internal-use >!--}
171
+ 处理 config.set 事件:找出受影响的适配器并触发 on_config_update
172
+ """
173
+ key = data.get("key", "")
174
+ if not key:
175
+ return
176
+ for instance in list(self._started_instances):
177
+ if not hasattr(instance, "on_config_update"):
178
+ continue
179
+ config_key = self._resolve_config_key(instance)
180
+ if key == config_key or key.startswith(config_key + "."):
181
+ new_dict = config.getConfig(config_key) or {}
182
+ self._notify_config_update(instance, None, None, new_dict)
183
+
184
+ def _on_config_updated(self, data: dict) -> None:
185
+ """
186
+ {!--< internal-use >!--}
187
+ 处理 config.updated 事件:对比新旧配置树,找出配置变化的适配器并触发 on_config_update
188
+ """
189
+ old_config = data.get("old_config", {}) or {}
190
+ new_config = data.get("new_config", {}) or {}
191
+ for instance in list(self._started_instances):
192
+ if not hasattr(instance, "on_config_update"):
193
+ continue
194
+ config_key = self._resolve_config_key(instance)
195
+ old_dict = old_config.get(config_key)
196
+ new_dict = new_config.get(config_key)
197
+ if old_dict != new_dict:
198
+ self._notify_config_update(instance, None, old_dict, new_dict)
199
+
200
+ @staticmethod
201
+ def _resolve_config_key(instance: Any) -> str:
202
+ """
203
+ {!--< internal-use >!--}
204
+ 解析适配器的配置键名(优先用 _get_config_key,回退类名)
205
+ """
206
+ get_key = getattr(instance, "_get_config_key", None)
207
+ if callable(get_key):
208
+ try:
209
+ return get_key()
210
+ except Exception:
211
+ pass
212
+ return instance.__class__.__name__
213
+
214
+ def _notify_config_update(
215
+ self,
216
+ instance: Any,
217
+ platform: str | None,
218
+ old_dict: dict | None,
219
+ new_dict: dict | None,
220
+ ) -> None:
221
+ """
222
+ {!--< internal-use >!--}
223
+ 调用适配器的 on_config_update 回调,传入类型安全的配置对象
224
+ """
225
+ config_class = getattr(instance, "ConfigClass", None)
226
+ try:
227
+ if config_class is not None:
228
+ from ..runtime.config_schema import dict_to_dataclass
229
+
230
+ old_config = (
231
+ dict_to_dataclass(config_class, old_dict) if old_dict else None
232
+ )
233
+ new_config = (
234
+ dict_to_dataclass(config_class, new_dict) if new_dict else None
235
+ )
236
+ else:
237
+ old_config = old_dict
238
+ new_config = new_dict
239
+ instance.on_config_update(old_config, new_config)
240
+ except Exception as e:
241
+ logger.error(
242
+ i18n.t(
243
+ "core.adapter.config_update_failed",
244
+ platform=platform or instance.__class__.__name__,
245
+ error=e,
246
+ )
247
+ )
248
+
155
249
  # ==================== 适配器注册与管理 ====================
156
250
 
157
251
  def register(
@@ -946,3 +946,10 @@ class HttpClient(BaseHttpClient):
946
946
 
947
947
  async def __aexit__(self, *args):
948
948
  await self.close()
949
+
950
+
951
+ __all__ = [
952
+ "ClientWebSocket",
953
+ "HttpClient",
954
+ "HttpResponse",
955
+ ]
@@ -272,6 +272,13 @@ class ConfigManager:
272
272
  self._cache_timestamp = time.time()
273
273
  self._dirty_keys.clear()
274
274
 
275
+ # 同步记录的 mtime,避免文件监听任务把框架自身的写入误判为外部修改,
276
+ # 从而重复触发 config.updated(与 config.set 路由重复调用 on_config_update)
277
+ try:
278
+ self._config_mtime = Path(self.CONFIG_FILE).stat().st_mtime
279
+ except OSError:
280
+ pass
281
+
275
282
  except Exception as e:
276
283
  try:
277
284
  from .logger import logger
@@ -620,3 +620,106 @@ DEFAULT_PROACTIVE_GC_INTERVAL_SECS: Final[int] = 300
620
620
  # 运行时行为。适配器关闭时取消所有 pending handler tasks 后等待它们退出的耐心时间。
621
621
  # 修改影响: 设大确保处理器完整结束,设小加速关闭流程。
622
622
  DEFAULT_HANDLER_DRAIN_TIMEOUT_SECS: Final[float] = 5.0
623
+
624
+ __all__ = [
625
+ "ADAPTER_RETRY_BACKOFF_INTERVALS",
626
+ "ADAPTER_RETRY_FIXED_DELAY_SECS",
627
+ "CONFIG_CACHE_TIMEOUT_SECS",
628
+ "CONFIG_KEY_ADAPTER_STATUS",
629
+ "CONFIG_KEY_ADAPTER_STATUS_OF",
630
+ "CONFIG_KEY_MODULES_STATUS",
631
+ "CONFIG_KEY_MODULE_STATUS_OF",
632
+ "CONFIG_KEY_ROUTER_CORS",
633
+ "CONFIG_KEY_ROUTER_SECURITY",
634
+ "CONFIG_ROOT_KEY",
635
+ "CONFIG_WRITE_DELAY_SECS",
636
+ "CONFIRM_HINT_WORDS",
637
+ "CONFIRM_NO_WORDS",
638
+ "CONFIRM_YES_WORDS",
639
+ "CONVERSATION_KEY_PREFIX",
640
+ "DEFAULT_ADAPTER_ENABLED",
641
+ "DEFAULT_COMMAND_ALLOW_SPACE_PREFIX",
642
+ "DEFAULT_COMMAND_CASE_SENSITIVE",
643
+ "DEFAULT_COMMAND_DISPATCHER_PRIORITY",
644
+ "DEFAULT_COMMAND_MUST_AT_BOT",
645
+ "DEFAULT_COMMAND_PREFIX",
646
+ "DEFAULT_CONFIG_FILE_PATH",
647
+ "DEFAULT_CORS_HEADERS",
648
+ "DEFAULT_CORS_MAX_AGE_SECS",
649
+ "DEFAULT_CORS_METHODS",
650
+ "DEFAULT_CORS_ORIGINS",
651
+ "DEFAULT_EVENT_SOURCE",
652
+ "DEFAULT_HANDLER_DRAIN_TIMEOUT_SECS",
653
+ "DEFAULT_HANDLER_MAX_CONCURRENCY",
654
+ "DEFAULT_HANDLER_PRIORITY",
655
+ "DEFAULT_HTTP_CLIENT_CONNECT_TIMEOUT_SECS",
656
+ "DEFAULT_HTTP_CLIENT_MAX_RETRIES",
657
+ "DEFAULT_HTTP_CLIENT_RETRY_DELAY_SECS",
658
+ "DEFAULT_HTTP_CLIENT_TIMEOUT_SECS",
659
+ "DEFAULT_HTTP_CLIENT_USER_AGENT",
660
+ "DEFAULT_HTTP_METHODS",
661
+ "DEFAULT_I18N_LANGUAGE",
662
+ "DEFAULT_KV_TABLE_NAME",
663
+ "DEFAULT_LAZY_LOADING_ENABLED",
664
+ "DEFAULT_LOG_LEVEL",
665
+ "DEFAULT_LOG_MEMORY_LIMIT",
666
+ "DEFAULT_MAX_RETRIES",
667
+ "DEFAULT_MESSAGE_IGNORE_SELF",
668
+ "DEFAULT_MODULE_ENABLED",
669
+ "DEFAULT_MODULE_PRIORITY",
670
+ "DEFAULT_OFFLINE_BOT_EXPIRY_SECS",
671
+ "DEFAULT_PROACTIVE_GC_INTERVAL_SECS",
672
+ "DEFAULT_RATE_LIMIT_CLEANUP_INTERVAL_SECS",
673
+ "DEFAULT_RATE_LIMIT_MAX_REQUESTS",
674
+ "DEFAULT_RATE_LIMIT_WINDOW_SECS",
675
+ "DEFAULT_SECURITY_HEADERS",
676
+ "DEFAULT_SEND_METHOD",
677
+ "DEFAULT_SEND_TARGET_TYPE",
678
+ "DEFAULT_SERVER_HOST",
679
+ "DEFAULT_SERVER_PORT",
680
+ "DEFAULT_STRICT_MODE",
681
+ "DEFAULT_UNINIT_TIMEOUT_SECS",
682
+ "DEFAULT_USE_GLOBAL_DB",
683
+ "DEFAULT_WAIT_TIMEOUT_SECS",
684
+ "DEFAULT_WS_AUTO_ACCEPT",
685
+ "DEFAULT_WS_CLIENT_CONNECT_TIMEOUT_SECS",
686
+ "DEFAULT_WS_CLIENT_HEARTBEAT_SECS",
687
+ "DETAIL_TYPE_CONNECT",
688
+ "DETAIL_TYPE_DISCONNECT",
689
+ "DETAIL_TYPE_FRIEND",
690
+ "DETAIL_TYPE_FRIEND_DECREASE",
691
+ "DETAIL_TYPE_FRIEND_INCREASE",
692
+ "DETAIL_TYPE_GROUP",
693
+ "DETAIL_TYPE_GROUP_MEMBER_DECREASE",
694
+ "DETAIL_TYPE_GROUP_MEMBER_INCREASE",
695
+ "DETAIL_TYPE_HEARTBEAT",
696
+ "DETAIL_TYPE_PRIVATE",
697
+ "DETAIL_TYPE_USER",
698
+ "EVENT_TYPE_MESSAGE",
699
+ "EVENT_TYPE_META",
700
+ "EVENT_TYPE_NOTICE",
701
+ "EVENT_TYPE_REQUEST",
702
+ "FALLBACK_IPV4",
703
+ "FALLBACK_IPV6_HOST",
704
+ "HANDLER_SLOW_THRESHOLD_SECS",
705
+ "LIFECYCLE_TIMER_CORE_INIT",
706
+ "LIFECYCLE_TIMER_CORE_UNINIT",
707
+ "LOGGER_NAME",
708
+ "LOG_RICH_THEME",
709
+ "LOG_TIME_FORMAT",
710
+ "RETCODE_NOT_IMPLEMENTED",
711
+ "RETCODE_OK",
712
+ "SERVER_SHUTDOWN_TIMEOUT_SECS",
713
+ "SQLITE_JOURNAL_MODE",
714
+ "SQLITE_SYNCHRONOUS_MODE",
715
+ "STATUS_FAILED",
716
+ "STATUS_OK",
717
+ "STORAGE_MAX_LIST_INDEX",
718
+ "TEXT_METHOD_INDICATORS",
719
+ "UNINIT_SETTLE_DELAY_SECS",
720
+ "UNKNOWN_PLATFORM",
721
+ "WILDCARD_IPV4",
722
+ "WILDCARD_IPV6",
723
+ "WS_CLOSE_INTERNAL_ERROR",
724
+ "WS_CLOSE_POLICY_VIOLATION",
725
+ ]
@@ -168,6 +168,7 @@ TRANSLATIONS = {
168
168
  "core.adapter.list_adapters_deprecated": "list_adapters() is deprecated, please use list_items() instead",
169
169
  "core.adapter.task_cancelled_debug": "Cancelled background startup task for platform {platform}",
170
170
  "core.adapter.platform_unregistered_short": "Platform {platform} not registered",
171
+ "core.adapter.config_update_failed": "Adapter {platform} config hot-reload callback failed: {error}",
171
172
  # ==================== Module Management ====================
172
173
  "core.module.set_sdk_failed": "Failed to set SDK reference: {error}",
173
174
  "core.module.param_must_be_class": "Parameter for module {name} must be a class, not {type}",
@@ -200,6 +201,7 @@ TRANSLATIONS = {
200
201
  "core.module.cleared": "Module manager has been fully cleared",
201
202
  "core.module.module_not_enabled": "Module {name} does not exist or is not enabled",
202
203
  "core.module.list_modules_deprecated": "list_modules() is deprecated, please use list_items() instead",
204
+ "core.module.config_update_failed": "Module {name} config hot-reload callback failed: {error}",
203
205
  # ==================== Router Management ====================
204
206
  "core.router.sse_path_exists": "SSE path {path} is already registered in module {module}",
205
207
  "core.router.register_sse": "[{module}] Registering SSE route: {path}",
@@ -168,6 +168,7 @@ TRANSLATIONS = {
168
168
  "core.adapter.list_adapters_deprecated": "list_adapters() は非推奨です、list_items() を使用してください",
169
169
  "core.adapter.task_cancelled_debug": "プラットフォーム {platform} のバックグラウンド起動タスクをキャンセルしました",
170
170
  "core.adapter.platform_unregistered_short": "プラットフォーム {platform} は登録されていません",
171
+ "core.adapter.config_update_failed": "アダプター {platform} の設定ホットリロードコールバックの実行に失敗しました: {error}",
171
172
  # ==================== モジュール管理 ====================
172
173
  "core.module.set_sdk_failed": "SDK 参照の設定に失敗しました: {error}",
173
174
  "core.module.param_must_be_class": "モジュール {name} のパラメーターはクラスでなければなりません、{type} ではありません",
@@ -200,6 +201,7 @@ TRANSLATIONS = {
200
201
  "core.module.cleared": "モジュールマネージャーは完全にクリアされました",
201
202
  "core.module.module_not_enabled": "モジュール {name} は存在しないか有効化されていません",
202
203
  "core.module.list_modules_deprecated": "list_modules() は非推奨です、list_items() を使用してください",
204
+ "core.module.config_update_failed": "モジュール {name} の設定ホットリロードコールバックの実行に失敗しました: {error}",
203
205
  # ==================== ルーター管理 ====================
204
206
  "core.router.sse_path_exists": "SSE パス {path} は既にモジュール {module} に登録されています",
205
207
  "core.router.register_sse": "[{module}] SSE ルートを登録しています: {path}",
@@ -168,6 +168,7 @@ TRANSLATIONS = {
168
168
  "core.adapter.list_adapters_deprecated": "list_adapters() устарел, используйте list_items()",
169
169
  "core.adapter.task_cancelled_debug": "Отменена фоновая задача запуска для платформы {platform}",
170
170
  "core.adapter.platform_unregistered_short": "Платформа {platform} не зарегистрирована",
171
+ "core.adapter.config_update_failed": "Сбой обратного вызова горячей перезагрузки конфигурации адаптера {platform}: {error}",
171
172
  # ==================== Управление модулями ====================
172
173
  "core.module.set_sdk_failed": "Ошибка установки ссылки на SDK: {error}",
173
174
  "core.module.param_must_be_class": "Параметр для модуля {name} должен быть классом, а не {type}",
@@ -200,6 +201,7 @@ TRANSLATIONS = {
200
201
  "core.module.cleared": "Менеджер модулей полностью очищен",
201
202
  "core.module.module_not_enabled": "Модуль {name} не существует или не включён",
202
203
  "core.module.list_modules_deprecated": "list_modules() устарел, используйте list_items()",
204
+ "core.module.config_update_failed": "Сбой обратного вызова горячей перезагрузки конфигурации модуля {name}: {error}",
203
205
  # ==================== Управление маршрутизацией ====================
204
206
  "core.router.sse_path_exists": "SSE путь {path} уже зарегистрирован в модуле {module}",
205
207
  "core.router.register_sse": "[{module}] Регистрация SSE маршрута: {path}",
@@ -168,6 +168,7 @@ TRANSLATIONS = {
168
168
  "core.adapter.list_adapters_deprecated": "list_adapters() 已弃用,请使用 list_items() 代替",
169
169
  "core.adapter.task_cancelled_debug": "已取消平台 {platform} 的后台启动任务",
170
170
  "core.adapter.platform_unregistered_short": "平台 {platform} 未注册",
171
+ "core.adapter.config_update_failed": "适配器 {platform} 配置热更新回调执行失败: {error}",
171
172
  # ==================== 模块管理 ====================
172
173
  "core.module.set_sdk_failed": "设置SDK引用失败: {error}",
173
174
  "core.module.param_must_be_class": "模块 {name} 的参数必须是类,而不是 {type}",
@@ -200,6 +201,7 @@ TRANSLATIONS = {
200
201
  "core.module.cleared": "模块管理器已完全清理",
201
202
  "core.module.module_not_enabled": "模块 {name} 不存在或未启用",
202
203
  "core.module.list_modules_deprecated": "list_modules() 已弃用,请使用 list_items() 代替",
204
+ "core.module.config_update_failed": "模块 {name} 配置热更新回调执行失败: {error}",
203
205
  # ==================== 路由管理 ====================
204
206
  "core.router.sse_path_exists": "SSE路径 {path} 已在模块 {module} 中注册",
205
207
  "core.router.register_sse": "[{module}] 注册SSE路由: {path}",
@@ -168,6 +168,7 @@ TRANSLATIONS = {
168
168
  "core.adapter.list_adapters_deprecated": "list_adapters() 已棄用,請使用 list_items() 代替",
169
169
  "core.adapter.task_cancelled_debug": "已取消平台 {platform} 的後台啟動任務",
170
170
  "core.adapter.platform_unregistered_short": "平台 {platform} 未註冊",
171
+ "core.adapter.config_update_failed": "適配器 {platform} 配置熱更新回呼執行失敗: {error}",
171
172
  # ==================== 模組管理 ====================
172
173
  "core.module.set_sdk_failed": "設定SDK參考失敗: {error}",
173
174
  "core.module.param_must_be_class": "模組 {name} 的參數必須是類別,而不是 {type}",
@@ -200,6 +201,7 @@ TRANSLATIONS = {
200
201
  "core.module.cleared": "模組管理器已完全清理",
201
202
  "core.module.module_not_enabled": "模組 {name} 不存在或未啟用",
202
203
  "core.module.list_modules_deprecated": "list_modules() 已棄用,請使用 list_items() 代替",
204
+ "core.module.config_update_failed": "模組 {name} 配置熱更新回呼執行失敗: {error}",
203
205
  # ==================== 路由管理 ====================
204
206
  "core.router.sse_path_exists": "SSE路徑 {path} 已在模組 {module} 中註冊",
205
207
  "core.router.register_sse": "[{module}] 註冊SSE路由: {path}",
@@ -249,3 +249,8 @@ class MasterManager:
249
249
 
250
250
  # 模块级单例
251
251
  master = MasterManager()
252
+
253
+ __all__ = [
254
+ "MasterManager",
255
+ "master",
256
+ ]
@@ -93,6 +93,8 @@ class ModuleManager(ManagerBase):
93
93
  str, Any
94
94
  ] = {} # 懒加载代理(未触发初始化时 get() 返回它)
95
95
  self._sdk = None
96
+ # 注册配置变更路由:将 config.set / config.updated 事件转发到各模块的 on_config_update
97
+ self._register_config_change_routing()
96
98
 
97
99
  def set_sdk_ref(self, sdk) -> bool:
98
100
  """
@@ -110,6 +112,100 @@ class ModuleManager(ManagerBase):
110
112
  logger.error(i18n.t("core.module.set_sdk_failed", error=e))
111
113
  return False
112
114
 
115
+ # ==================== 配置变更路由 ====================
116
+
117
+ def _register_config_change_routing(self) -> None:
118
+ """
119
+ {!--< internal-use >!--}
120
+ 注册 config.set / config.updated 事件订阅,将配置变更路由到各模块的 on_config_update
121
+
122
+ - ``config.set``:代码或 Dashboard 调用 setConfig 时即时触发(单 key 变更)
123
+ - ``config.updated``:用户手动编辑配置文件后由文件监听任务触发(整树变更)
124
+ """
125
+ lifecycle.register("config.set", self._on_config_set)
126
+ lifecycle.register("config.updated", self._on_config_updated)
127
+
128
+ def _on_config_set(self, data: dict) -> None:
129
+ """
130
+ {!--< internal-use >!--}
131
+ 处理 config.set 事件:找出受影响的模块并触发 on_config_update
132
+ """
133
+ key = data.get("key", "")
134
+ if not key:
135
+ return
136
+ for module_name in list(self._loaded_modules):
137
+ instance = self._modules.get(module_name)
138
+ if not instance or not hasattr(instance, "on_config_update"):
139
+ continue
140
+ config_key = self._resolve_config_key(instance)
141
+ # key 形如 "MyModule" 或 "MyModule.field"
142
+ if key == config_key or key.startswith(config_key + "."):
143
+ new_dict = config.getConfig(config_key) or {}
144
+ self._notify_config_update(instance, module_name, None, new_dict)
145
+
146
+ def _on_config_updated(self, data: dict) -> None:
147
+ """
148
+ {!--< internal-use >!--}
149
+ 处理 config.updated 事件:对比新旧配置树,找出配置变化的模块并触发 on_config_update
150
+ """
151
+ old_config = data.get("old_config", {}) or {}
152
+ new_config = data.get("new_config", {}) or {}
153
+ for module_name in list(self._loaded_modules):
154
+ instance = self._modules.get(module_name)
155
+ if not instance or not hasattr(instance, "on_config_update"):
156
+ continue
157
+ config_key = self._resolve_config_key(instance)
158
+ old_dict = old_config.get(config_key)
159
+ new_dict = new_config.get(config_key)
160
+ if old_dict != new_dict:
161
+ self._notify_config_update(instance, module_name, old_dict, new_dict)
162
+
163
+ @staticmethod
164
+ def _resolve_config_key(instance: Any) -> str:
165
+ """
166
+ {!--< internal-use >!--}
167
+ 解析模块的配置键名(优先用注入的注册名,回退类名)
168
+ """
169
+ return getattr(instance, "_module_name", None) or instance.__class__.__name__
170
+
171
+ def _notify_config_update(
172
+ self,
173
+ instance: Any,
174
+ module_name: str,
175
+ old_dict: dict | None,
176
+ new_dict: dict | None,
177
+ ) -> None:
178
+ """
179
+ {!--< internal-use >!--}
180
+ 调用模块的 on_config_update 回调,传入类型安全的配置对象
181
+
182
+ :param instance: 模块实例
183
+ :param module_name: 模块名(用于日志)
184
+ :param old_dict: 变更前的配置字典(可能为 None)
185
+ :param new_dict: 变更后的配置字典(可能为 None)
186
+ """
187
+ config_class = getattr(instance, "ConfigClass", None)
188
+ try:
189
+ if config_class is not None:
190
+ from ..runtime.config_schema import dict_to_dataclass
191
+
192
+ old_config = (
193
+ dict_to_dataclass(config_class, old_dict) if old_dict else None
194
+ )
195
+ new_config = (
196
+ dict_to_dataclass(config_class, new_dict) if new_dict else None
197
+ )
198
+ else:
199
+ old_config = old_dict
200
+ new_config = new_dict
201
+ instance.on_config_update(old_config, new_config)
202
+ except Exception as e:
203
+ logger.error(
204
+ i18n.t(
205
+ "core.module.config_update_failed", name=module_name, error=e
206
+ )
207
+ )
208
+
113
209
  # ==================== 模块注册与管理 ====================
114
210
 
115
211
  def register(
@@ -59,15 +59,30 @@ uninit = sdk.uninit
59
59
 
60
60
  # 导出列表
61
61
  __all__ = [
62
+ "BaseAdapter",
63
+ "BatchContext",
64
+ "Event",
62
65
  "LazyModule",
66
+ "SendBuilder",
67
+ "SendContext",
68
+ "SendDSL",
63
69
  "__author__",
64
70
  "__version__",
71
+ "adapter",
72
+ "config",
73
+ "env",
74
+ "i18n",
65
75
  "init",
66
76
  "init_sync",
67
77
  "init_task",
78
+ "lifecycle",
68
79
  "load_module",
80
+ "logger",
81
+ "module",
69
82
  "restart",
83
+ "router",
70
84
  "run",
71
85
  "sdk",
86
+ "storage",
72
87
  "uninit",
73
88
  ]
File without changes
File without changes
File without changes