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.
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/PKG-INFO +1 -1
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/pyproject.toml +1 -1
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/__init__.py +2 -1
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/__init__.pyi +1 -1
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/client.py +7 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/errors.py +11 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/kv_builder.py +5 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/router.py +7 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/send_builder.py +6 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/send_rules.py +6 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/websocket.py +6 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/adapter.py +94 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/client.py +7 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/config.py +7 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/constants.py +103 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/en.py +2 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/ja.py +2 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/ru.py +2 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/zh_cn.py +2 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/zh_tw.py +2 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/master.py +5 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/module.py +96 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/__init__.py +15 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/.gitignore +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/LICENSE +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/README.pypi.md +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/__init__.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/__init__.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/base.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/base.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/cli.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/cli.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/__init__.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/__init__.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/create.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/create.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/init.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/init.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/install.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/install.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/language.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/language.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/list.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/list.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/list_remote.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/list_remote.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/run.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/run.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/self_update.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/self_update.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/types.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/types.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/uninstall.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/uninstall.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/upgrade.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/commands/upgrade.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/console.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/console.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/hints.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/hints.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/__init__.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/__init__.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/__init__.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/__init__.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/en.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/en.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/ja.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/ja.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/ru.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/ru.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/zh_cn.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/zh_cn.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/zh_tw.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/i18n/locales/zh_tw.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/registry.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/registry.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/utils/__init__.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/utils/__init__.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/utils/display.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/utils/display.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/utils/file_watcher.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/utils/file_watcher.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/utils/package_manager.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/CLI/utils/package_manager.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/adapter.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/adapter.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/client.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/errors.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/kv_builder.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/manager.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/manager.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/module.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/module.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/router.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/send_builder.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/send_rules.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/storage.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/storage.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Bases/websocket.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/__init__.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/__init__.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/base.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/base.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/command.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/command.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/message.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/message.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/message_builder.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/message_builder.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/meta.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/meta.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/notice.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/notice.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/request.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/request.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/session_type.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/session_type.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/wrapper.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/Event/wrapper.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/__init__.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/__init__.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/adapter.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/assets/__init__.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/assets/__init__.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/assets/error.css +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/assets/error.html +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/assets/root.css +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/assets/root.html +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/client.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/config.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/constants.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/__init__.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/__init__.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/constants.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/constants.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/__init__.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/__init__.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/en.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/ja.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/ru.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/zh_cn.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/i18n/locales/zh_tw.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/lifecycle.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/lifecycle.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/logger.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/logger.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/master.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/module.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/router.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/router.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/storage.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/Core/storage.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/__init__.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/__main__.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/__main__.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/__init__.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/__init__.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/adapter.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/adapter.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/bases/__init__.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/bases/__init__.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/bases/finder.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/bases/finder.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/module.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/finders/module.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/__init__.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/__init__.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/adapter.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/adapter.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/bases/__init__.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/bases/__init__.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/bases/loader.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/bases/loader.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/module.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/module.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/strategy.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/strategy.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/strict.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/loaders/strict.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/py.typed +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/__init__.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/__init__.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/config_schema.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/config_schema.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/context.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/context.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/exceptions.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/exceptions.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/frame_config.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/frame_config.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/hints.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/hints.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/tasks.py +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/runtime/tasks.pyi +0 -0
- {erispulse-2.6.2 → erispulse-2.6.3.dev0}/src/ErisPulse/sdk.py +0 -0
- {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.
|
|
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.
|
|
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
|
|
@@ -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
|
+
]
|
|
@@ -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(
|
|
@@ -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}",
|
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|