ErisPulse 2.8.5__tar.gz → 2.9.0.dev1__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 (142) hide show
  1. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/.gitignore +2 -1
  2. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/PKG-INFO +4 -3
  3. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/pyproject.toml +20 -4
  4. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/create.py +2 -0
  5. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/run.py +9 -4
  6. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/constants.py +11 -0
  7. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/utils/package_manager.py +7 -12
  8. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/__init__.py +8 -0
  9. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/adapter.py +62 -656
  10. erispulse-2.9.0.dev1/src/ErisPulse/Core/Bases/api_dsl.py +698 -0
  11. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/config_schema.py +215 -17
  12. erispulse-2.9.0.dev1/src/ErisPulse/Core/Bases/model.py +1167 -0
  13. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/module.py +8 -0
  14. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/send_rules.py +8 -2
  15. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/sql_base.py +175 -13
  16. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/__init__.py +14 -0
  17. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/base.py +76 -7
  18. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/command.py +609 -22
  19. erispulse-2.9.0.dev1/src/ErisPulse/Core/Event/command_args.py +539 -0
  20. erispulse-2.9.0.dev1/src/ErisPulse/Core/Event/conversation.py +773 -0
  21. erispulse-2.9.0.dev1/src/ErisPulse/Core/Event/governance.py +474 -0
  22. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/interaction.py +3 -2
  23. erispulse-2.9.0.dev1/src/ErisPulse/Core/Event/message.py +299 -0
  24. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/overrides.py +10 -8
  25. erispulse-2.9.0.dev1/src/ErisPulse/Core/Event/throttle.py +180 -0
  26. erispulse-2.9.0.dev1/src/ErisPulse/Core/Event/trace.py +134 -0
  27. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/wrapper.py +54 -748
  28. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/__init__.py +19 -1
  29. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/adapter.py +206 -94
  30. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/client.py +24 -19
  31. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/config.py +49 -24
  32. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/constants.py +74 -7
  33. erispulse-2.9.0.dev1/src/ErisPulse/Core/di.py +226 -0
  34. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/i18n/locales/en.py +79 -3
  35. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/i18n/locales/ja.py +79 -3
  36. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/i18n/locales/ru.py +79 -3
  37. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/i18n/locales/zh_cn.py +79 -3
  38. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/i18n/locales/zh_tw.py +79 -3
  39. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/lifecycle.py +137 -70
  40. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/logger.py +3 -3
  41. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/master.py +1 -1
  42. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/module.py +231 -187
  43. erispulse-2.9.0.dev1/src/ErisPulse/Core/ownership.py +517 -0
  44. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/router.py +207 -71
  45. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/scope.py +326 -190
  46. erispulse-2.9.0.dev1/src/ErisPulse/Core/shadow.py +497 -0
  47. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/storage/mysql.py +23 -0
  48. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/storage/postgres.py +19 -0
  49. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/storage/sqlite.py +11 -2
  50. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/text_match.py +1 -1
  51. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/transcript.py +55 -4
  52. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/loaders/module.py +222 -1
  53. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/__init__.py +8 -0
  54. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/diagnostics.py +126 -0
  55. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/exceptions.py +9 -0
  56. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/file_watcher.py +29 -2
  57. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/plugin_reload.py +3 -2
  58. erispulse-2.9.0.dev1/src/ErisPulse/runtime/proactive_gc.py +292 -0
  59. erispulse-2.9.0.dev1/src/ErisPulse/runtime/sdk_initializer.py +708 -0
  60. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/tasks.py +8 -2
  61. erispulse-2.9.0.dev1/src/ErisPulse/runtime/troubleshoot.py +233 -0
  62. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/sdk.py +35 -921
  63. erispulse-2.8.5/src/ErisPulse/Core/Event/message.py +0 -197
  64. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/LICENSE +0 -0
  65. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/README.pypi.md +0 -0
  66. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/__init__.py +0 -0
  67. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/base.py +0 -0
  68. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/cli.py +0 -0
  69. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/__init__.py +0 -0
  70. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/config.py +0 -0
  71. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/doctor.py +0 -0
  72. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/init.py +0 -0
  73. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/install.py +0 -0
  74. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/language.py +0 -0
  75. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/list.py +0 -0
  76. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/list_remote.py +0 -0
  77. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/self_update.py +0 -0
  78. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/types.py +0 -0
  79. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/uninstall.py +0 -0
  80. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/upgrade.py +0 -0
  81. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/commands/version.py +0 -0
  82. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/console.py +0 -0
  83. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/hints.py +0 -0
  84. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/i18n/__init__.py +0 -0
  85. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/i18n/locales/__init__.py +0 -0
  86. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/i18n/locales/en.py +0 -0
  87. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/i18n/locales/ja.py +0 -0
  88. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/i18n/locales/ru.py +0 -0
  89. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/i18n/locales/zh_cn.py +0 -0
  90. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/i18n/locales/zh_tw.py +0 -0
  91. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/registry.py +0 -0
  92. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/utils/__init__.py +0 -0
  93. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/utils/config_wizard.py +0 -0
  94. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/utils/display.py +0 -0
  95. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/CLI/utils/scaffold_text.py +0 -0
  96. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/client.py +0 -0
  97. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/converter.py +0 -0
  98. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/errors.py +0 -0
  99. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/i18n_schema.py +0 -0
  100. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/kv_builder.py +0 -0
  101. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/manager.py +0 -0
  102. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/router.py +0 -0
  103. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/send_builder.py +0 -0
  104. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/storage.py +0 -0
  105. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Bases/websocket.py +0 -0
  106. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/message_builder.py +0 -0
  107. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/meta.py +0 -0
  108. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/notice.py +0 -0
  109. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/request.py +0 -0
  110. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/Event/session_type.py +0 -0
  111. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/assets/__init__.py +0 -0
  112. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/assets/error.css +0 -0
  113. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/assets/error.html +0 -0
  114. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/assets/root.css +0 -0
  115. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/assets/root.html +0 -0
  116. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/i18n/__init__.py +0 -0
  117. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/i18n/constants.py +0 -0
  118. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/i18n/locales/__init__.py +0 -0
  119. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/Core/storage/__init__.py +0 -0
  120. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/__init__.py +0 -0
  121. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/__main__.py +0 -0
  122. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/finders/__init__.py +0 -0
  123. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/finders/adapter.py +0 -0
  124. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/finders/bases/__init__.py +0 -0
  125. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/finders/bases/finder.py +0 -0
  126. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/finders/module.py +0 -0
  127. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/loaders/__init__.py +0 -0
  128. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/loaders/adapter.py +0 -0
  129. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/loaders/bases/__init__.py +0 -0
  130. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/loaders/bases/loader.py +0 -0
  131. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/loaders/plugin_folder.py +0 -0
  132. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/loaders/strategy.py +0 -0
  133. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/loaders/strict.py +0 -0
  134. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/py.typed +0 -0
  135. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/config_schema.py +0 -0
  136. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/context.py +0 -0
  137. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/example_config.py +0 -0
  138. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/frame_config.py +0 -0
  139. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/hints.py +0 -0
  140. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/memory.py +0 -0
  141. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/owner_cleanup.py +0 -0
  142. {erispulse-2.8.5 → erispulse-2.9.0.dev1}/src/ErisPulse/runtime/version.py +0 -0
@@ -5,7 +5,6 @@ plugins/
5
5
  venvs
6
6
  config.full.example
7
7
  config.toml
8
- uv.lock
9
8
  snapshots/
10
9
  logs/
11
10
  config.db*
@@ -239,3 +238,5 @@ pyvenv.cfg
239
238
 
240
239
  # 但保留源中文文档
241
240
  !docs/zh-CN/
241
+
242
+ .zcode/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: ErisPulse
3
- Version: 2.8.5
3
+ Version: 2.9.0-dev.1
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
@@ -24,6 +24,7 @@ Classifier: Programming Language :: Python :: 3.10
24
24
  Classifier: Programming Language :: Python :: 3.11
25
25
  Classifier: Programming Language :: Python :: 3.12
26
26
  Classifier: Programming Language :: Python :: 3.13
27
+ Classifier: Programming Language :: Python :: 3.14
27
28
  Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
28
29
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
29
30
  Classifier: Typing :: Typed
@@ -33,7 +34,7 @@ Requires-Dist: aiosqlite>=0.20.0
33
34
  Requires-Dist: fastapi>=0.116.1
34
35
  Requires-Dist: rich>=13.0.0
35
36
  Requires-Dist: tomlkit>=0.15.1
36
- Requires-Dist: uvicorn>=0.30.0
37
+ Requires-Dist: uvicorn>=0.35.0
37
38
  Requires-Dist: websockets>=12.0
38
39
  Provides-Extra: mysql
39
40
  Requires-Dist: aiomysql>=0.2.0; extra == 'mysql'
@@ -42,9 +43,9 @@ Requires-Dist: asyncpg>=0.29.0; extra == 'postgres'
42
43
  Provides-Extra: test
43
44
  Requires-Dist: httpx>=0.24.0; extra == 'test'
44
45
  Requires-Dist: pytest-asyncio>=0.21.0; extra == 'test'
45
- Requires-Dist: pytest-benchmark>=4.0.0; extra == 'test'
46
46
  Requires-Dist: pytest-cov>=4.0.0; extra == 'test'
47
47
  Requires-Dist: pytest-mock>=3.10.0; extra == 'test'
48
+ Requires-Dist: pytest-timeout>=2.1.0; extra == 'test'
48
49
  Requires-Dist: pytest-xdist>=3.0.0; extra == 'test'
49
50
  Requires-Dist: pytest>=7.0.0; extra == 'test'
50
51
  Description-Content-Type: text/markdown
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "ErisPulse"
7
- version = "2.8.5"
7
+ version = "2.9.0-dev.1"
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"
@@ -51,6 +51,7 @@ classifiers = [
51
51
  "Programming Language :: Python :: 3.11",
52
52
  "Programming Language :: Python :: 3.12",
53
53
  "Programming Language :: Python :: 3.13",
54
+ "Programming Language :: Python :: 3.14",
54
55
  "Programming Language :: Python :: 3 :: Only",
55
56
  "Operating System :: OS Independent",
56
57
  "Topic :: Software Development :: Libraries :: Python Modules",
@@ -66,7 +67,7 @@ dependencies = [
66
67
  "websockets>=12.0",
67
68
  "aiohttp>=3.9.0",
68
69
  "fastapi>=0.116.1",
69
- "uvicorn>=0.30.0",
70
+ "uvicorn>=0.35.0",
70
71
  # storage 相关(默认 SQLite 后端异步驱动,开箱即用)
71
72
  "aiosqlite>=0.20.0",
72
73
  ]
@@ -92,12 +93,14 @@ test = [
92
93
  "pytest-cov>=4.0.0",
93
94
  "pytest-asyncio>=0.21.0",
94
95
  "pytest-xdist>=3.0.0",
96
+ "pytest-timeout>=2.1.0",
95
97
  "pytest-mock>=3.10.0",
96
- "pytest-benchmark>=4.0.0",
97
98
  "httpx>=0.24.0",
98
99
  ]
99
100
 
100
101
  [dependency-groups]
102
+ # 测试依赖统一维护于 [project.optional-dependencies].test(公开 extras,
103
+ # 生态可 pip install ErisPulse[test]);此处的 test 组已删除以免双处漂移。
101
104
  dev = [
102
105
  "pyclean>=3.6.0",
103
106
  "ruff>=0.1.7",
@@ -105,6 +108,9 @@ dev = [
105
108
  "typing_extensions>=4.7.0; python_version < '3.11'",
106
109
  ]
107
110
 
111
+ [tool.uv]
112
+ default-groups = ["dev"]
113
+
108
114
  [project.scripts]
109
115
  ep-init = "ErisPulse.__init__:init_sync"
110
116
  epsdk = "ErisPulse.__main__:main"
@@ -130,7 +136,7 @@ include = [
130
136
  target-version = "py310"
131
137
  line-length = 120
132
138
 
133
- include = ["src/**/*.py", "tests/**/*.py"]
139
+ include = ["src/**/*.py", "tests/**/*.py", "scripts/**/*.py", "examples/**/*.py"]
134
140
 
135
141
  extend-exclude = [
136
142
  "__pycache__",
@@ -168,6 +174,7 @@ ignore = [
168
174
  "RUF003", # ambiguous-unicode-character-comment
169
175
 
170
176
  # 框架/异步代码风格性规则(强行修会破坏 API 或语义)
177
+ "B008", # function-call-in-default-argument —— 依赖注入(Depends)声明的标准形态,DI 框架惯例豁免
171
178
  "PLC0415", # import-outside-top-level —— 异步框架中 lazy import 是常用且必要的模式
172
179
  "PLR0911", # too-many-return-statements
173
180
  "PLR0912", # too-many-branches
@@ -208,6 +215,13 @@ ignore = [
208
215
 
209
216
  [tool.ruff.lint.per-file-ignores]
210
217
  "__init__.py" = ["F401", "PLC0415", "I001"] # 导出式 __init__ 经常按需导入
218
+ # 旧版生成/翻译脚本:存量风格债渐进收编(新脚本 check_i18n_locales/check_docs_links/
219
+ # release_check/_common 已全净)。TODO: 逐步修复后移除本段。
220
+ "scripts/tools/translate-docs.py" = ["PERF401", "PTH", "UP035", "B", "RET505", "FURB", "RUF013", "UP008", "A001", "SIM"]
221
+ "scripts/tools/check-translation.py" = ["PERF401", "PTH", "UP035", "B", "RET505", "FURB", "RUF013", "SIM"]
222
+ "scripts/tools/generate-api-docs.py" = ["PERF401", "PTH", "UP035", "B", "RET505", "FURB", "RUF013", "A001", "SIM", "W29", "E501"]
223
+ "scripts/tools/generate-docs-index.py" = ["PERF401", "PTH", "UP035", "B", "RET505", "FURB", "RUF013", "RUF015", "SIM"]
224
+ "scripts/tools/generate-type-stubs.py" = ["PERF401", "PTH", "UP035", "B", "RET505", "FURB", "RUF013", "ANN", "A001", "PLW0603", "SIM", "W29"]
211
225
  "tests/**/*.py" = [
212
226
  # 断言/夹具相关(测试代码天然模式)
213
227
  "S101", "PLR2004", "SLF001", "ARG", "ANN", "PTH",
@@ -282,6 +296,8 @@ python_classes = "Test*"
282
296
  python_functions = "test_*"
283
297
  minversion = "7.0"
284
298
  addopts = [
299
+ "--timeout=120",
300
+ "--timeout-method=thread",
285
301
  "-v",
286
302
  "--strict-markers",
287
303
  "--strict-config",
@@ -219,6 +219,8 @@ class Main(BaseModule):
219
219
  # 跨命令的用户黑白名单用覆写系统 ACL
220
220
  # (ErisPulse.event.overrides.acl 或 overrides.acl.set(name, allow/deny),命令名支持 glob);
221
221
  # 模块级可用性 / 事件准入 / 出站限制由作用域 scope 管理(用户可控)
222
+ # 命令支持声明式参数与选项(args= / options=):框架自动解析并按名注入处理器参数,
223
+ # 用户输入错误自动回复本地化提示与用法(类型:str/int/float/bool/literal/duration/rest)
222
224
  @command(\"hello\", help=i18n.t(\"module.{name}.command.hello.help\"))
223
225
  async def hello_command(event: Event):
224
226
  await event.reply(i18n.t(\"module.{name}.command.hello.reply\"))
@@ -19,7 +19,13 @@ from rich.panel import Panel
19
19
  from ...runtime.file_watcher import FileSystemEventHandler, PollingObserver
20
20
  from ..base import Command
21
21
  from ..console import console
22
- from ..constants import ENV_SUPERVISED, HARD_RESTART_EXIT_CODE
22
+ from ..constants import (
23
+ ENV_SUPERVISED,
24
+ HARD_RESTART_EXIT_CODE,
25
+ RUN_CRASH_BACKOFF_MAX_SECS,
26
+ RUN_CRASH_BACKOFF_PER_CRASH_SECS,
27
+ RUN_RESTART_PAUSE_SECS,
28
+ )
23
29
  from ..i18n import i18n
24
30
  from ..utils.package_manager import (
25
31
  resolve_target_python,
@@ -152,7 +158,6 @@ class RunCommand(Command):
152
158
  self._run_internal(reload_mode)
153
159
 
154
160
  _RESTART_EXIT_CODE = HARD_RESTART_EXIT_CODE
155
- _MAX_CRASH_BACKOFF = 60.0
156
161
 
157
162
  def _run_internal(self, reload_mode: bool):
158
163
  """
@@ -213,7 +218,7 @@ class RunCommand(Command):
213
218
  if process.returncode == self._RESTART_EXIT_CODE:
214
219
  console.print(f"[info]{i18n.t('cli.run.restart_request')}[/]")
215
220
  crash_count = 0
216
- time.sleep(0.5)
221
+ time.sleep(RUN_RESTART_PAUSE_SECS)
217
222
  continue
218
223
 
219
224
  if process.returncode == 0:
@@ -224,7 +229,7 @@ class RunCommand(Command):
224
229
  # 非硬重启/非正常退出码:模块/适配器内部错误导致子进程异常终止
225
230
  # 不退出主进程,等待后自动重试
226
231
  crash_count += 1
227
- backoff = min(self._MAX_CRASH_BACKOFF, 3.0 * crash_count)
232
+ backoff = min(RUN_CRASH_BACKOFF_MAX_SECS, RUN_CRASH_BACKOFF_PER_CRASH_SECS * crash_count)
228
233
  console.print(
229
234
  f"[warning]{i18n.t('cli.run.process_crashed', code=process.returncode)}[/]"
230
235
  )
@@ -43,8 +43,19 @@ ADAPTER_ENTRY_POINT_GROUP: str = "erispulse.adapter"
43
43
  # PyPI JSON API URL 模板(仅 CLI 做包查询 / 自更新检查时使用)。
44
44
  PYPI_PACKAGE_JSON_URL_TEMPLATE: str = "https://pypi.org/pypi/{package}/json"
45
45
 
46
+ # run 命令子进程监督的退避参数。
47
+ # 使用位置: CLI/commands/run.py -> 监督循环。
48
+ # 修改影响: 每次崩溃的重试间隔 = min(MAX, PER_CRASH x 崩溃次数);
49
+ # RESTART_PAUSE 为硬重启请求后的短暂停顿(让端口等资源释放)。
50
+ RUN_CRASH_BACKOFF_MAX_SECS: float = 60.0
51
+ RUN_CRASH_BACKOFF_PER_CRASH_SECS: float = 3.0
52
+ RUN_RESTART_PAUSE_SECS: float = 0.5
53
+
46
54
  __all__ = [
47
55
  "ADAPTER_ENTRY_POINT_GROUP",
56
+ "RUN_CRASH_BACKOFF_MAX_SECS",
57
+ "RUN_CRASH_BACKOFF_PER_CRASH_SECS",
58
+ "RUN_RESTART_PAUSE_SECS",
48
59
  "ENV_SUPERVISED",
49
60
  "HARD_RESTART_EXIT_CODE",
50
61
  "MODULE_ENTRY_POINT_GROUP",
@@ -1711,15 +1711,18 @@ def append_pyproject_dependencies(project_dir: Path, packages: "list[str]") -> b
1711
1711
  :return: 是否成功(pyproject 不存在 / 解析失败返回 False)
1712
1712
  """
1713
1713
  import tomlkit
1714
- import tomllib
1715
1714
 
1716
1715
  pyproject = Path(project_dir) / "pyproject.toml"
1717
1716
  if not pyproject.exists():
1718
1717
  return False
1719
1718
  try:
1720
- with pyproject.open("rb") as f:
1721
- doc = tomllib.load(f)
1722
- deps: list = doc.get("project", {}).get("dependencies", [])
1719
+ # tomlkit 解析保留注释与格式(其文档为 dict 子类,get 行为与
1720
+ # tomllib 一致;不用 tomllib——它是 Python 3.11+ 标准库)
1721
+ doc_kit = tomlkit.parse(pyproject.read_text(encoding="utf-8"))
1722
+ proj = doc_kit.get("project")
1723
+ if proj is None:
1724
+ return False
1725
+ deps: list = proj.get("dependencies", [])
1723
1726
  added = False
1724
1727
  for pkg in packages:
1725
1728
  if not any(str(d).split("[;")[0].split("==")[0].split(">=")[0].strip().lower() == pkg.lower() for d in deps):
@@ -1727,11 +1730,6 @@ def append_pyproject_dependencies(project_dir: Path, packages: "list[str]") -> b
1727
1730
  added = True
1728
1731
  if not added:
1729
1732
  return True
1730
- # tomllib 读的是普通 dict——用 tomlkit 重新解析原文件以保留格式后写回
1731
- doc_kit = tomlkit.parse(pyproject.read_text(encoding="utf-8"))
1732
- proj = doc_kit.get("project")
1733
- if proj is None:
1734
- return False
1735
1733
  proj["dependencies"] = deps
1736
1734
  pyproject.write_text(tomlkit.dumps(doc_kit), encoding="utf-8")
1737
1735
  return True
@@ -1848,8 +1846,6 @@ def warn_if_uv_isolated() -> bool:
1848
1846
 
1849
1847
  :return: 是否处于隔离场景(True = 已输出警告)
1850
1848
  """
1851
- import tomllib
1852
-
1853
1849
  if "UV" not in os.environ:
1854
1850
  return False
1855
1851
  if Path("pyproject.toml").exists():
@@ -1859,7 +1855,6 @@ def warn_if_uv_isolated() -> bool:
1859
1855
  + i18n.t("cli.uv.isolated_warning")
1860
1856
  + "[/]"
1861
1857
  )
1862
- _ = tomllib # 保留显式依赖提示位(pyproject 探测未来可深化)
1863
1858
  return True
1864
1859
 
1865
1860
 
@@ -44,6 +44,7 @@ from .config_schema import (
44
44
  BotAccountConfig,
45
45
  I18nConfig,
46
46
  )
47
+ from .model import BaseModel, ColumnExpr, Condition, Field, Model, QuerySet, relationship
47
48
  from .i18n_schema import (
48
49
  BaseI18n,
49
50
  I18nKey,
@@ -63,6 +64,7 @@ __all__ = [
63
64
  "BaseHttpResponse",
64
65
  # i18n 键声明 Schema 基类(命名对齐 BaseConfig)
65
66
  "BaseI18n",
67
+ "BaseModel",
66
68
  "BaseModule",
67
69
  "BaseQueryBuilder",
68
70
  "BaseStorage",
@@ -71,7 +73,10 @@ __all__ = [
71
73
  "ClientConnectionError",
72
74
  "ClientError",
73
75
  "ClientTimeoutError",
76
+ "Condition",
77
+ "ColumnExpr",
74
78
  "ErisPulseError",
79
+ "Field",
75
80
  "HTTPStatusError",
76
81
  "HttpRequest",
77
82
  # i18n 配置 Schema(控制显示语言)
@@ -82,11 +87,14 @@ __all__ = [
82
87
  "InteractionCancelled",
83
88
  "InteractionError",
84
89
  "KVQueryBuilder",
90
+ "Model",
85
91
  "ModuleCallError",
86
92
  "ModuleCallTimeoutError",
87
93
  "ModuleError",
88
94
  "ModuleMeta",
89
95
  "ModuleNotAvailableError",
96
+ "QuerySet",
97
+ "relationship",
90
98
  "RequestDSL",
91
99
  "SendBuilder",
92
100
  "SendContext",