ErisPulse 2.9.0.dev1__tar.gz → 2.10.0.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.9.0.dev1 → erispulse-2.10.0.dev0}/.gitignore +6 -2
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/PKG-INFO +4 -1
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/README.pypi.md +2 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/pyproject.toml +3 -1
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/cli.py +12 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/commands/create.py +84 -16
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/commands/doctor.py +47 -1
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/commands/init.py +28 -22
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/commands/install.py +10 -6
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/commands/list.py +40 -6
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/commands/run.py +20 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/commands/self_update.py +5 -4
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/commands/types.py +27 -31
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/commands/upgrade.py +9 -3
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/constants.py +13 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/i18n/locales/en.py +27 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/i18n/locales/ja.py +27 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/i18n/locales/ru.py +27 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/i18n/locales/zh_cn.py +27 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/i18n/locales/zh_tw.py +27 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/utils/config_wizard.py +7 -6
- erispulse-2.10.0.dev0/src/ErisPulse/CLI/utils/interactive.py +127 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/utils/package_manager.py +16 -9
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/utils/scaffold_text.py +62 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Bases/__init__.py +16 -1
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Bases/adapter.py +13 -12
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Bases/client.py +25 -3
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Bases/errors.py +87 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Bases/kv_builder.py +4 -2
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Bases/router.py +100 -12
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Bases/sql_base.py +11 -6
- erispulse-2.10.0.dev0/src/ErisPulse/Core/Bases/websocket.py +477 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Event/base.py +22 -19
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Event/command.py +6 -4
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Event/conversation.py +62 -13
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Event/governance.py +10 -4
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Event/overrides.py +64 -40
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/__init__.py +28 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/adapter.py +111 -11
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/client.py +35 -4
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/config.py +359 -13
- erispulse-2.10.0.dev0/src/ErisPulse/Core/connections.py +555 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/constants.py +142 -1
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/i18n/__init__.py +94 -19
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/i18n/locales/en.py +42 -2
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/i18n/locales/ja.py +42 -2
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/i18n/locales/ru.py +42 -2
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/i18n/locales/zh_cn.py +42 -2
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/i18n/locales/zh_tw.py +42 -2
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/lifecycle.py +10 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/logger.py +80 -9
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/module.py +56 -3
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/ownership.py +98 -30
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/router.py +422 -53
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/scope.py +3 -3
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/shadow.py +15 -14
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/text_match.py +3 -1
- erispulse-2.10.0.dev0/src/ErisPulse/Core/transcript.py +817 -0
- erispulse-2.10.0.dev0/src/ErisPulse/__init__.py +426 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/loaders/module.py +168 -8
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/loaders/plugin_folder.py +5 -1
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/runtime/__init__.py +17 -1
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/runtime/sdk_initializer.py +9 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/runtime/tasks.py +232 -3
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/runtime/troubleshoot.py +38 -30
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/sdk.py +30 -3
- erispulse-2.9.0.dev1/src/ErisPulse/Core/Bases/websocket.py +0 -271
- erispulse-2.9.0.dev1/src/ErisPulse/Core/transcript.py +0 -426
- erispulse-2.9.0.dev1/src/ErisPulse/__init__.py +0 -108
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/LICENSE +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/__init__.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/base.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/commands/__init__.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/commands/config.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/commands/language.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/commands/list_remote.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/commands/uninstall.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/commands/version.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/console.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/hints.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/i18n/__init__.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/i18n/locales/__init__.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/registry.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/utils/__init__.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/CLI/utils/display.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Bases/api_dsl.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Bases/config_schema.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Bases/converter.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Bases/i18n_schema.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Bases/manager.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Bases/model.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Bases/module.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Bases/send_builder.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Bases/send_rules.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Bases/storage.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Event/__init__.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Event/command_args.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Event/interaction.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Event/message.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Event/message_builder.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Event/meta.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Event/notice.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Event/request.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Event/session_type.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Event/throttle.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Event/trace.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/Event/wrapper.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/assets/__init__.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/assets/error.css +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/assets/error.html +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/assets/root.css +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/assets/root.html +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/di.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/i18n/constants.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/i18n/locales/__init__.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/master.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/storage/__init__.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/storage/mysql.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/storage/postgres.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/Core/storage/sqlite.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/__main__.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/finders/__init__.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/finders/adapter.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/finders/bases/__init__.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/finders/bases/finder.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/finders/module.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/loaders/__init__.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/loaders/adapter.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/loaders/bases/__init__.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/loaders/bases/loader.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/loaders/strategy.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/loaders/strict.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/py.typed +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/runtime/config_schema.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/runtime/context.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/runtime/diagnostics.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/runtime/example_config.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/runtime/exceptions.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/runtime/file_watcher.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/runtime/frame_config.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/runtime/hints.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/runtime/memory.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/runtime/owner_cleanup.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/runtime/plugin_reload.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/runtime/proactive_gc.py +0 -0
- {erispulse-2.9.0.dev1 → erispulse-2.10.0.dev0}/src/ErisPulse/runtime/version.py +0 -0
|
@@ -122,7 +122,7 @@ ipython_config.py
|
|
|
122
122
|
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
123
123
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
124
124
|
# commonly ignored for libraries.
|
|
125
|
-
|
|
125
|
+
uv.lock
|
|
126
126
|
|
|
127
127
|
# poetry
|
|
128
128
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
@@ -239,4 +239,8 @@ pyvenv.cfg
|
|
|
239
239
|
# 但保留源中文文档
|
|
240
240
|
!docs/zh-CN/
|
|
241
241
|
|
|
242
|
-
.zcode/
|
|
242
|
+
.zcode/
|
|
243
|
+
|
|
244
|
+
.github/assets/ErisPulseFilm1.mp4
|
|
245
|
+
.github/assets/score1.wav
|
|
246
|
+
.github/assets/score2.wav
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ErisPulse
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.10.0-dev.0
|
|
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
|
|
@@ -38,6 +38,7 @@ Requires-Dist: uvicorn>=0.35.0
|
|
|
38
38
|
Requires-Dist: websockets>=12.0
|
|
39
39
|
Provides-Extra: mysql
|
|
40
40
|
Requires-Dist: aiomysql>=0.2.0; extra == 'mysql'
|
|
41
|
+
Requires-Dist: cryptography>=41.0.0; extra == 'mysql'
|
|
41
42
|
Provides-Extra: postgres
|
|
42
43
|
Requires-Dist: asyncpg>=0.29.0; extra == 'postgres'
|
|
43
44
|
Provides-Extra: test
|
|
@@ -94,6 +95,8 @@ It ships with a flexible plugin system, hot reload, a visual Dashboard, an AI Bu
|
|
|
94
95
|
pip install ErisPulse
|
|
95
96
|
```
|
|
96
97
|
|
|
98
|
+
For a global `epsdk` CLI without any virtual environment, use `uv tool install ErisPulse` instead.
|
|
99
|
+
|
|
97
100
|
### Option 2 — Docker (recommended for production)
|
|
98
101
|
|
|
99
102
|
```bash
|
|
@@ -42,6 +42,8 @@ It ships with a flexible plugin system, hot reload, a visual Dashboard, an AI Bu
|
|
|
42
42
|
pip install ErisPulse
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
+
For a global `epsdk` CLI without any virtual environment, use `uv tool install ErisPulse` instead.
|
|
46
|
+
|
|
45
47
|
### Option 2 — Docker (recommended for production)
|
|
46
48
|
|
|
47
49
|
```bash
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ErisPulse"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.10.0-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"
|
|
@@ -84,6 +84,8 @@ Changelog = "https://github.com/ErisPulse/ErisPulse/blob/main/CHANGELOG.md"
|
|
|
84
84
|
# 存储后端可选驱动:pip install ErisPulse[mysql] / ErisPulse[postgres]
|
|
85
85
|
mysql = [
|
|
86
86
|
"aiomysql>=0.2.0",
|
|
87
|
+
# MySQL 8 默认 caching_sha2_password 认证要求(缺失时连接池初始化失败)
|
|
88
|
+
"cryptography>=41.0.0",
|
|
87
89
|
]
|
|
88
90
|
postgres = [
|
|
89
91
|
"asyncpg>=0.29.0",
|
|
@@ -305,6 +305,11 @@ class CLI:
|
|
|
305
305
|
args, unknown = self.parser.parse_known_args()
|
|
306
306
|
args._unknown_args = unknown
|
|
307
307
|
|
|
308
|
+
# --yes/-y:assume-yes 模式,由统一交互封装(utils/interactive)消费
|
|
309
|
+
from .utils.interactive import set_assume_yes
|
|
310
|
+
|
|
311
|
+
set_assume_yes(bool(getattr(args, "yes", False)))
|
|
312
|
+
|
|
308
313
|
# --no-color:禁用 Rich 控制台着色(CI / 日志采集场景)
|
|
309
314
|
if getattr(args, "no_color", False):
|
|
310
315
|
console.no_color = True
|
|
@@ -375,6 +380,13 @@ class CLI:
|
|
|
375
380
|
console.print(f"\n[warning]{i18n.t('cli.run.user_interrupted')}[/]")
|
|
376
381
|
sys.exit(1)
|
|
377
382
|
except Exception as e:
|
|
383
|
+
from .utils.interactive import NonInteractiveError
|
|
384
|
+
|
|
385
|
+
if isinstance(e, NonInteractiveError):
|
|
386
|
+
# 非交互环境遇到无法自动应答的提示:明确报错而非 EOF 崩溃
|
|
387
|
+
console.print(f"[error]{e}[/]")
|
|
388
|
+
console.print(f"[hint]{i18n.t('cli.interactive.non_tty_hint')}[/]")
|
|
389
|
+
sys.exit(1)
|
|
378
390
|
console.print(f"[error]{i18n.t('cli.run.exec_error', error=e)}[/]")
|
|
379
391
|
# 场景化友好提示:根据异常类型给出下一步建议
|
|
380
392
|
from .hints import suggest_for_exception
|
|
@@ -41,6 +41,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
41
41
|
SOFTWARE.
|
|
42
42
|
"""
|
|
43
43
|
|
|
44
|
+
# 生成模块/适配器模板的最低 SDK 地板(写入模板 min_sdk_version 字段)。
|
|
45
|
+
# 模板示例使用 args=/options=(2.9 特性);pip 默认不解析预发布版本,
|
|
46
|
+
# 该地板不得高于已发布的正式版本,否则生成的组件会因依赖装不上或
|
|
47
|
+
# 加载器按 PEP 440 拒载(与 CLI/constants.py 的 INIT_ERISPULSE_DEPENDENCY 同步升版)。
|
|
48
|
+
_TEMPLATE_MIN_SDK_VERSION = "2.9.0"
|
|
49
|
+
|
|
44
50
|
_MODULE_PYPROJECT = """[project]
|
|
45
51
|
name = "ErisPulse-{name}"
|
|
46
52
|
version = "1.0.0"
|
|
@@ -72,10 +78,19 @@ _MODULE_INIT = """from .Core import Main
|
|
|
72
78
|
|
|
73
79
|
_MODULE_CORE = """from dataclasses import dataclass, field
|
|
74
80
|
|
|
75
|
-
from ErisPulse import
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
81
|
+
from ErisPulse import (
|
|
82
|
+
SDK,
|
|
83
|
+
BaseConfig,
|
|
84
|
+
BaseI18n,
|
|
85
|
+
BaseModule,
|
|
86
|
+
Event,
|
|
87
|
+
I18nKey,
|
|
88
|
+
ModuleMeta,
|
|
89
|
+
command,
|
|
90
|
+
i18n,
|
|
91
|
+
message,
|
|
92
|
+
notice,
|
|
93
|
+
)
|
|
79
94
|
|
|
80
95
|
|
|
81
96
|
class Main(BaseModule):
|
|
@@ -144,6 +159,42 @@ class Main(BaseModule):
|
|
|
144
159
|
ru=\"Привет от {name}!\",
|
|
145
160
|
zh_TW=\"來自 {name} 的問候!\",
|
|
146
161
|
)
|
|
162
|
+
roll_help: I18nKey = I18nKey(
|
|
163
|
+
key=\"module.{name}.command.roll.help\",
|
|
164
|
+
default=\"Roll dice: count [sides]\",
|
|
165
|
+
zh_CN=\"掷骰子:次数 [面数]\",
|
|
166
|
+
en=\"Roll dice: count [sides]\",
|
|
167
|
+
ja=\"サイコロを振る: 回数 [面数]\",
|
|
168
|
+
ru=\"Бросить кости: количество [граней]\",
|
|
169
|
+
zh_TW=\"擲骰子:次數 [面數]\",
|
|
170
|
+
)
|
|
171
|
+
roll_reply: I18nKey = I18nKey(
|
|
172
|
+
key=\"module.{name}.command.roll.reply\",
|
|
173
|
+
default=\"Rolled {{count}}d{{sides}}, total: {{total}}{{detail}}\",
|
|
174
|
+
zh_CN=\"掷了 {{count}} 次 {{sides}} 面骰,总点数:{{total}}{{detail}}\",
|
|
175
|
+
en=\"Rolled {{count}}d{{sides}}, total: {{total}}{{detail}}\",
|
|
176
|
+
ja=\"{{sides}}面ダイスを {{count}} 回振った合計: {{total}}{{detail}}\",
|
|
177
|
+
ru=\"Бросков {{count}}d{{sides}}, сумма: {{total}}{{detail}}\",
|
|
178
|
+
zh_TW=\"擲了 {{count}} 次 {{sides}} 面骰,總點數:{{total}}{{detail}}\",
|
|
179
|
+
)
|
|
180
|
+
roll_detail: I18nKey = I18nKey(
|
|
181
|
+
key=\"module.{name}.command.roll.detail\",
|
|
182
|
+
default=\" (verbose: {{count}} rolls of {{sides}}-sided dice)\",
|
|
183
|
+
zh_CN=\"(详细模式:{{count}} 次 {{sides}} 面骰)\",
|
|
184
|
+
en=\" (verbose: {{count}} rolls of {{sides}}-sided dice)\",
|
|
185
|
+
ja=\"(詳細モード: {{sides}}面ダイスを {{count}} 回)\",
|
|
186
|
+
ru=\" (подробно: {{count}} бросков {{sides}}-гранного кубика)\",
|
|
187
|
+
zh_TW=\"(詳細模式:{{count}} 次 {{sides}} 面骰)\",
|
|
188
|
+
)
|
|
189
|
+
signin_reply: I18nKey = I18nKey(
|
|
190
|
+
key=\"module.{name}.command.signin.reply\",
|
|
191
|
+
default=\"Signed in!\",
|
|
192
|
+
zh_CN=\"签到成功\",
|
|
193
|
+
en=\"Signed in!\",
|
|
194
|
+
ja=\"チェックイン完了!\",
|
|
195
|
+
ru=\"Готово, вы отмечены!\",
|
|
196
|
+
zh_TW=\"簽到成功\",
|
|
197
|
+
)
|
|
147
198
|
|
|
148
199
|
def __init__(self, sdk: SDK = None):
|
|
149
200
|
# sdk 由框架在实例化时自动注入(无需手动导入兜底)
|
|
@@ -167,7 +218,7 @@ class Main(BaseModule):
|
|
|
167
218
|
version=\"0.1.0\",
|
|
168
219
|
author=\"ErisDev\",
|
|
169
220
|
# 最低 SDK 版本(可选):不满足时框架在加载期明确报错并跳过本模块
|
|
170
|
-
min_sdk_version=\"
|
|
221
|
+
min_sdk_version=\"{min_sdk}\",
|
|
171
222
|
group=\"default\",
|
|
172
223
|
tags=[\"{name}\"],
|
|
173
224
|
# 对外服务白名单(可选):声明后其他模块可经 sdk.module.call() 调用这些方法;
|
|
@@ -225,6 +276,20 @@ class Main(BaseModule):
|
|
|
225
276
|
async def hello_command(event: Event):
|
|
226
277
|
await event.reply(i18n.t(\"module.{name}.command.hello.reply\"))
|
|
227
278
|
|
|
279
|
+
# {text[module.roll_hint]}
|
|
280
|
+
@command(
|
|
281
|
+
\"roll\",
|
|
282
|
+
args=\"<count:int> [sides:int=6]\",
|
|
283
|
+
options={{\"verbose\": \"-v/--verbose\"}},
|
|
284
|
+
help=i18n.t(\"module.{name}.command.roll.help\"),
|
|
285
|
+
)
|
|
286
|
+
async def roll_command(event: Event, count: int, sides: int = 6, verbose: bool = False):
|
|
287
|
+
import random
|
|
288
|
+
|
|
289
|
+
total = sum(random.randint(1, sides) for _ in range(count))
|
|
290
|
+
detail = i18n.t(\"module.{name}.command.roll.detail\", count=count, sides=sides) if verbose else \"\"
|
|
291
|
+
await event.reply(i18n.t(\"module.{name}.command.roll.reply\", count=count, sides=sides, total=total, detail=detail))
|
|
292
|
+
|
|
228
293
|
async def _register_message_handlers(self):
|
|
229
294
|
@message.on_private_message()
|
|
230
295
|
async def private_message_handler(event: Event):
|
|
@@ -235,9 +300,9 @@ class Main(BaseModule):
|
|
|
235
300
|
pass
|
|
236
301
|
|
|
237
302
|
# 消息装饰器支持 pattern(glob 通配符)/ regex(正则),不匹配则不触发
|
|
238
|
-
@message.on_message(pattern=\"
|
|
303
|
+
@message.on_message(pattern=\"{text[module.signin_pattern]}\")
|
|
239
304
|
async def signin_handler(event: Event):
|
|
240
|
-
await event.reply(\"
|
|
305
|
+
await event.reply(i18n.t(\"module.{name}.command.signin.reply\"))
|
|
241
306
|
|
|
242
307
|
@notice.on_friend_add()
|
|
243
308
|
async def friend_add_handler(event: Event):
|
|
@@ -283,10 +348,7 @@ _ADAPTER_CORE = """import asyncio
|
|
|
283
348
|
import json
|
|
284
349
|
from dataclasses import dataclass, field
|
|
285
350
|
from typing import ClassVar
|
|
286
|
-
from ErisPulse
|
|
287
|
-
from ErisPulse.Core.Bases import BaseConfig, BaseI18n, I18nKey
|
|
288
|
-
from ErisPulse.Core import router
|
|
289
|
-
from ErisPulse.Core.i18n import i18n
|
|
351
|
+
from ErisPulse import BaseAdapter, BaseConfig, BaseI18n, I18nKey, router, i18n
|
|
290
352
|
|
|
291
353
|
|
|
292
354
|
class {name}(BaseAdapter):
|
|
@@ -294,7 +356,7 @@ class {name}(BaseAdapter):
|
|
|
294
356
|
{text[adapter.doc]}
|
|
295
357
|
\"\"\"
|
|
296
358
|
|
|
297
|
-
# 依赖声明(可选,ErisPulse 2.
|
|
359
|
+
# 依赖声明(可选,ErisPulse 2.9.0+):
|
|
298
360
|
# depends = {{"adapters": [], "modules": []}} # 硬依赖:缺失时跳过启动
|
|
299
361
|
# optional_modules = [] # 软依赖:就绪/丢失时收到
|
|
300
362
|
# # on_dependency_ready/lost 回调
|
|
@@ -302,7 +364,7 @@ class {name}(BaseAdapter):
|
|
|
302
364
|
optional_modules: ClassVar[list] = []
|
|
303
365
|
|
|
304
366
|
# 声明所需最低 SDK 版本:不满足时框架在加载期明确报错并跳过本适配器(可选)
|
|
305
|
-
min_sdk_version = "
|
|
367
|
+
min_sdk_version = "{min_sdk}"
|
|
306
368
|
|
|
307
369
|
# {text[adapter.config_hint]}
|
|
308
370
|
@dataclass
|
|
@@ -461,6 +523,11 @@ class {name}(BaseAdapter):
|
|
|
461
523
|
async def _ws_handler(self, websocket):
|
|
462
524
|
bot_id = self._get_bot_id()
|
|
463
525
|
|
|
526
|
+
# 连接已由框架自动登记进连接池(ErisPulse.connections):
|
|
527
|
+
# meta 供跨模块查看,join_group 后可被 connections.broadcast 定向推送
|
|
528
|
+
websocket.meta["bot_id"] = bot_id
|
|
529
|
+
websocket.join_group(f"bot:{{bot_id}}")
|
|
530
|
+
|
|
464
531
|
await self.emit_meta("connect", bot_id, user_name="{name}")
|
|
465
532
|
self.logger.info("{text[adapter.log.bot_connected]}")
|
|
466
533
|
|
|
@@ -484,7 +551,7 @@ class {name}(BaseAdapter):
|
|
|
484
551
|
|
|
485
552
|
async def call_api(self, endpoint: str, **params):
|
|
486
553
|
\"\"\"Call platform API\"\"\"
|
|
487
|
-
from ErisPulse
|
|
554
|
+
from ErisPulse import client
|
|
488
555
|
|
|
489
556
|
cfg = self.cfg
|
|
490
557
|
headers = {{"Authorization": "Bearer " + cfg.token}}
|
|
@@ -848,7 +915,7 @@ class CreateCommand(Command):
|
|
|
848
915
|
|
|
849
916
|
(pkg_dir / "__init__.py").write_text(_MODULE_INIT, encoding="utf-8")
|
|
850
917
|
(pkg_dir / "Core.py").write_text(
|
|
851
|
-
_MODULE_CORE.format(name=name, text=_scaffold_text(name)),
|
|
918
|
+
_MODULE_CORE.format(name=name, text=_scaffold_text(name), min_sdk=_TEMPLATE_MIN_SDK_VERSION),
|
|
852
919
|
encoding="utf-8",
|
|
853
920
|
)
|
|
854
921
|
(project_dir / "pyproject.toml").write_text(
|
|
@@ -921,7 +988,7 @@ class CreateCommand(Command):
|
|
|
921
988
|
|
|
922
989
|
(plugin_dir / "__init__.py").write_text(_MODULE_INIT, encoding="utf-8")
|
|
923
990
|
(plugin_dir / "Core.py").write_text(
|
|
924
|
-
_MODULE_CORE.format(name=name, text=_scaffold_text(name)),
|
|
991
|
+
_MODULE_CORE.format(name=name, text=_scaffold_text(name), min_sdk=_TEMPLATE_MIN_SDK_VERSION),
|
|
925
992
|
encoding="utf-8",
|
|
926
993
|
)
|
|
927
994
|
|
|
@@ -1000,6 +1067,7 @@ class CreateCommand(Command):
|
|
|
1000
1067
|
converter_name=converter_name,
|
|
1001
1068
|
entry_key=entry_key,
|
|
1002
1069
|
text=_scaffold_text(name),
|
|
1070
|
+
min_sdk=_TEMPLATE_MIN_SDK_VERSION,
|
|
1003
1071
|
),
|
|
1004
1072
|
encoding="utf-8",
|
|
1005
1073
|
)
|
|
@@ -95,7 +95,7 @@ class DoctorCommand(Command):
|
|
|
95
95
|
pip_note = (
|
|
96
96
|
i18n.t("cli.doctor.venv_pip_ok")
|
|
97
97
|
if venv_pip.exists()
|
|
98
|
-
else "
|
|
98
|
+
else i18n.t("cli.doctor.venv_pip_uv")
|
|
99
99
|
)
|
|
100
100
|
rows.append(
|
|
101
101
|
(
|
|
@@ -133,6 +133,52 @@ class DoctorCommand(Command):
|
|
|
133
133
|
)
|
|
134
134
|
failed = True
|
|
135
135
|
|
|
136
|
+
# 4.5 组件配置健康(配置文件存在 ≠ 必填项齐全:复用配置向导的
|
|
137
|
+
# schema 状态检测,"装好了跑不起来"多因适配器必填项缺失)
|
|
138
|
+
try:
|
|
139
|
+
from ..utils.config_wizard import (
|
|
140
|
+
STATUS_INCOMPLETE,
|
|
141
|
+
get_target_status,
|
|
142
|
+
load_config_targets,
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
incomplete: list[str] = []
|
|
146
|
+
for target in load_config_targets():
|
|
147
|
+
status, _errors = get_target_status(target)
|
|
148
|
+
# 仅"待完善"(开了但必填项缺失)判 FAIL;完全未配置属
|
|
149
|
+
# 用户尚未开始配置,不算故障
|
|
150
|
+
if status == STATUS_INCOMPLETE:
|
|
151
|
+
incomplete.append(target.name)
|
|
152
|
+
if incomplete:
|
|
153
|
+
failed = True
|
|
154
|
+
rows.append(
|
|
155
|
+
(
|
|
156
|
+
self._status(False),
|
|
157
|
+
i18n.t("cli.doctor.component_config"),
|
|
158
|
+
i18n.t(
|
|
159
|
+
"cli.doctor.component_config_incomplete",
|
|
160
|
+
names=", ".join(incomplete),
|
|
161
|
+
),
|
|
162
|
+
)
|
|
163
|
+
)
|
|
164
|
+
else:
|
|
165
|
+
rows.append(
|
|
166
|
+
(
|
|
167
|
+
self._status(True),
|
|
168
|
+
i18n.t("cli.doctor.component_config"),
|
|
169
|
+
i18n.t("cli.doctor.component_config_ok"),
|
|
170
|
+
)
|
|
171
|
+
)
|
|
172
|
+
except Exception:
|
|
173
|
+
# 发现失败(如依赖缺失)不阻塞其余诊断项
|
|
174
|
+
rows.append(
|
|
175
|
+
(
|
|
176
|
+
self._status(True),
|
|
177
|
+
i18n.t("cli.doctor.component_config"),
|
|
178
|
+
i18n.t("cli.doctor.component_config_skipped"),
|
|
179
|
+
)
|
|
180
|
+
)
|
|
181
|
+
|
|
136
182
|
# 5. PyPI 连通性
|
|
137
183
|
try:
|
|
138
184
|
remote = asyncio.run(pm.get_remote_packages())
|
|
@@ -11,14 +11,15 @@ import sys
|
|
|
11
11
|
from argparse import ArgumentParser
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
|
|
14
|
-
from rich.prompt import Confirm, IntPrompt
|
|
15
14
|
from rich.text import Text
|
|
16
15
|
|
|
17
16
|
from ..base import Command
|
|
18
17
|
from ..console import console
|
|
18
|
+
from ..constants import INIT_ERISPULSE_DEPENDENCY
|
|
19
19
|
from ..i18n import i18n
|
|
20
20
|
from ..utils import PackageManager
|
|
21
21
|
from ..utils.display import _input, prompt_validated, section_header
|
|
22
|
+
from ..utils.interactive import confirm, select
|
|
22
23
|
from ..utils.package_manager import (
|
|
23
24
|
append_pyproject_dependencies,
|
|
24
25
|
create_project_venv,
|
|
@@ -26,6 +27,7 @@ from ..utils.package_manager import (
|
|
|
26
27
|
uv_add,
|
|
27
28
|
warn_if_uv_isolated,
|
|
28
29
|
)
|
|
30
|
+
from ..utils.scaffold_text import ScaffoldText
|
|
29
31
|
|
|
30
32
|
|
|
31
33
|
def _validate_project_name(name: str) -> bool:
|
|
@@ -192,6 +194,9 @@ class InitCommand(Command):
|
|
|
192
194
|
console.print(f"[success] {i18n.t('cli.init.created_dir', name=project_name)}[/]")
|
|
193
195
|
|
|
194
196
|
try:
|
|
197
|
+
# 生成物文案(config 注释 / main docstring / .gitignore 分节 /
|
|
198
|
+
# README)跟随 CLI 语言;缺失键回退英文
|
|
199
|
+
st = ScaffoldText()
|
|
195
200
|
for dir_name in ["config", "logs"]:
|
|
196
201
|
(project_path / dir_name).mkdir(exist_ok=True)
|
|
197
202
|
# SSL 证书默认目录:跟随项目运行目录走,配置里用相对路径引用
|
|
@@ -201,15 +206,14 @@ class InitCommand(Command):
|
|
|
201
206
|
ssl_file = ssl_dir / ssl_name
|
|
202
207
|
if not ssl_file.exists():
|
|
203
208
|
ssl_file.write_text(
|
|
204
|
-
"
|
|
209
|
+
st.t("init.ssl_placeholder") + "\n",
|
|
205
210
|
encoding="utf-8",
|
|
206
211
|
)
|
|
207
212
|
|
|
208
213
|
config_file = project_path / "config" / "config.toml"
|
|
209
214
|
if not config_file.exists():
|
|
210
215
|
with config_file.open("w", encoding="utf-8") as f:
|
|
211
|
-
f.write("
|
|
212
|
-
f.write("# 完整配置示例请参考 config.full.example\n\n")
|
|
216
|
+
f.write(st.t("init.config_toml_header") + "\n\n")
|
|
213
217
|
f.write("[ErisPulse.server]\n")
|
|
214
218
|
f.write('host = "0.0.0.0"\n')
|
|
215
219
|
f.write("port = 8000\n\n")
|
|
@@ -224,9 +228,7 @@ class InitCommand(Command):
|
|
|
224
228
|
main_file = project_path / "main.py"
|
|
225
229
|
if not main_file.exists():
|
|
226
230
|
with main_file.open("w", encoding="utf-8") as f:
|
|
227
|
-
f.write(
|
|
228
|
-
f.write("这是 ErisPulse 自动生成的主程序文件\n")
|
|
229
|
-
f.write('"""\n\n')
|
|
231
|
+
f.write(st.t("init.main_docstring", display_name=display_name) + "\n")
|
|
230
232
|
f.write("import asyncio\n")
|
|
231
233
|
f.write("from ErisPulse import sdk\n\n")
|
|
232
234
|
f.write("async def main():\n")
|
|
@@ -245,7 +247,7 @@ class InitCommand(Command):
|
|
|
245
247
|
f.write('description = "ErisPulse project"\n')
|
|
246
248
|
f.write('requires-python = ">=3.10"\n')
|
|
247
249
|
f.write("dependencies = [\n")
|
|
248
|
-
f.write(' "
|
|
250
|
+
f.write(f' "{INIT_ERISPULSE_DEPENDENCY}",\n')
|
|
249
251
|
for adapter in adapter_list or []:
|
|
250
252
|
f.write(f' "{adapter}",\n')
|
|
251
253
|
f.write("]\n")
|
|
@@ -265,13 +267,13 @@ class InitCommand(Command):
|
|
|
265
267
|
"*.egg-info/\n"
|
|
266
268
|
".eggs/\n"
|
|
267
269
|
"\n"
|
|
268
|
-
"
|
|
270
|
+
f"{st.t('init.gitignore_section_venv')}\n"
|
|
269
271
|
".venv/\n"
|
|
270
272
|
"venv/\n"
|
|
271
273
|
"env/\n"
|
|
272
274
|
".env\n"
|
|
273
275
|
"\n"
|
|
274
|
-
"
|
|
276
|
+
f"{st.t('init.gitignore_section_cache')}\n"
|
|
275
277
|
".pytest_cache/\n"
|
|
276
278
|
".mypy_cache/\n"
|
|
277
279
|
".ruff_cache/\n"
|
|
@@ -279,11 +281,11 @@ class InitCommand(Command):
|
|
|
279
281
|
"coverage.xml\n"
|
|
280
282
|
"htmlcov/\n"
|
|
281
283
|
"\n"
|
|
282
|
-
"
|
|
284
|
+
f"{st.t('init.gitignore_section_runtime')}\n"
|
|
283
285
|
"config/\n"
|
|
284
286
|
"logs/\n"
|
|
285
287
|
"\n"
|
|
286
|
-
"
|
|
288
|
+
f"{st.t('init.gitignore_section_editor')}\n"
|
|
287
289
|
".idea/\n"
|
|
288
290
|
".vscode/\n"
|
|
289
291
|
"*.swp\n"
|
|
@@ -295,14 +297,14 @@ class InitCommand(Command):
|
|
|
295
297
|
readme_file = project_path / "README.md"
|
|
296
298
|
if not readme_file.exists():
|
|
297
299
|
with readme_file.open("w", encoding="utf-8") as f:
|
|
298
|
-
f.write(
|
|
300
|
+
f.write(st.t("init.readme_body", display_name=display_name))
|
|
299
301
|
console.print(f"[success] {i18n.t('cli.init.readme_created')}[/]")
|
|
300
302
|
|
|
301
303
|
# ---- 虚拟环境与依赖安装 ----
|
|
302
304
|
if create_venv:
|
|
303
305
|
console.print(f"[info] {i18n.t('cli.init.venv_creating')}[/]")
|
|
304
306
|
venv_python = None
|
|
305
|
-
if uv_add(project_path, [
|
|
307
|
+
if uv_add(project_path, [INIT_ERISPULSE_DEPENDENCY]):
|
|
306
308
|
# uv add 自动创建 .venv、安装依赖并写入 pyproject 依赖清单
|
|
307
309
|
venv_python = resolve_target_python(project_path)[0]
|
|
308
310
|
console.print(f"[success] {i18n.t('cli.init.venv_created')}[/]")
|
|
@@ -312,8 +314,8 @@ class InitCommand(Command):
|
|
|
312
314
|
if venv_python:
|
|
313
315
|
console.print(f"[success] {i18n.t('cli.init.venv_created')}[/]")
|
|
314
316
|
pm = PackageManager(python_executable=venv_python)
|
|
315
|
-
if pm.install_package([
|
|
316
|
-
append_pyproject_dependencies(project_path, [
|
|
317
|
+
if pm.install_package([INIT_ERISPULSE_DEPENDENCY]):
|
|
318
|
+
append_pyproject_dependencies(project_path, [INIT_ERISPULSE_DEPENDENCY])
|
|
317
319
|
console.print(f"[success] {i18n.t('cli.init.deps_installed')}[/]")
|
|
318
320
|
else:
|
|
319
321
|
console.print(
|
|
@@ -432,7 +434,11 @@ class InitCommand(Command):
|
|
|
432
434
|
f" [bold]2.[/] {i18n.t('cli.init.location_option_new')} [dim]— {i18n.t('cli.init.location_desc_new')}[/]"
|
|
433
435
|
)
|
|
434
436
|
console.print()
|
|
435
|
-
location_choice =
|
|
437
|
+
location_choice = int(
|
|
438
|
+
select(
|
|
439
|
+
i18n.t("cli.create.select_prompt"), choices=["1", "2"], default="2"
|
|
440
|
+
)
|
|
441
|
+
)
|
|
436
442
|
console.print()
|
|
437
443
|
in_current_dir = location_choice == 1
|
|
438
444
|
|
|
@@ -458,7 +464,7 @@ class InitCommand(Command):
|
|
|
458
464
|
project_name = p.name
|
|
459
465
|
project_path = (Path(target_dir) if target_dir else Path()) / project_name
|
|
460
466
|
if project_path.exists() and not force:
|
|
461
|
-
if not
|
|
467
|
+
if not confirm(
|
|
462
468
|
f" [cyan]{i18n.t('cli.init.dir_overwrite_prompt', name=project_name)}[/]",
|
|
463
469
|
default=False,
|
|
464
470
|
):
|
|
@@ -467,10 +473,10 @@ class InitCommand(Command):
|
|
|
467
473
|
|
|
468
474
|
# 虚拟环境与 git 仓库问询
|
|
469
475
|
if not getattr(self, "no_venv", False):
|
|
470
|
-
create_venv =
|
|
476
|
+
create_venv = confirm(
|
|
471
477
|
f" [cyan]{i18n.t('cli.init.venv_prompt')}[/]", default=True
|
|
472
478
|
)
|
|
473
|
-
git_init =
|
|
479
|
+
git_init = confirm(
|
|
474
480
|
f" [cyan]{i18n.t('cli.init.git_prompt')}[/]", default=False
|
|
475
481
|
)
|
|
476
482
|
|
|
@@ -521,7 +527,7 @@ class InitCommand(Command):
|
|
|
521
527
|
console.print(f"[warning] {i18n.t('cli.init.invalid_port', port=new_port)}[/]")
|
|
522
528
|
new_port = _input(">")
|
|
523
529
|
|
|
524
|
-
if
|
|
530
|
+
if confirm(
|
|
525
531
|
f"\n [cyan]{i18n.t('cli.init.configure_adapters_prompt')}[/]",
|
|
526
532
|
default=True,
|
|
527
533
|
):
|
|
@@ -587,7 +593,7 @@ class InitCommand(Command):
|
|
|
587
593
|
|
|
588
594
|
console.print(f"[dim] {i18n.t('cli.init.adapters_enabled', count=len(enabled))}[/]")
|
|
589
595
|
|
|
590
|
-
if enabled and
|
|
596
|
+
if enabled and confirm(f" [cyan]{i18n.t('cli.init.install_selected_prompt')}[/]", default=True):
|
|
591
597
|
self._install_adapters(enabled, adapters)
|
|
592
598
|
|
|
593
599
|
def _install_adapters(self, adapter_names, adapters_info):
|
|
@@ -8,7 +8,7 @@ import asyncio
|
|
|
8
8
|
import sys
|
|
9
9
|
from argparse import ArgumentParser
|
|
10
10
|
|
|
11
|
-
from rich.prompt import
|
|
11
|
+
from rich.prompt import Prompt
|
|
12
12
|
from rich.text import Text
|
|
13
13
|
|
|
14
14
|
from ..base import Command
|
|
@@ -16,6 +16,7 @@ from ..console import console
|
|
|
16
16
|
from ..i18n import i18n
|
|
17
17
|
from ..utils import PackageManager, config_wizard
|
|
18
18
|
from ..utils.display import interactive_select_table
|
|
19
|
+
from ..utils.interactive import confirm
|
|
19
20
|
from ..utils.package_manager import (
|
|
20
21
|
resolve_target_python,
|
|
21
22
|
warn_if_uv_isolated,
|
|
@@ -251,6 +252,7 @@ class InstallCommand(Command):
|
|
|
251
252
|
if success:
|
|
252
253
|
# 非交互路径不进入向导,仅提示后续配置入口
|
|
253
254
|
console.print(f"[dim] {i18n.t('cli.install.configure_hint')}[/]")
|
|
255
|
+
console.print(f"[hint] {i18n.t('cli.install.done_hint')}[/]")
|
|
254
256
|
|
|
255
257
|
if not success:
|
|
256
258
|
sys.exit(1)
|
|
@@ -294,7 +296,7 @@ class InstallCommand(Command):
|
|
|
294
296
|
elif choice == "4":
|
|
295
297
|
self._install_custom(upgrade, pre)
|
|
296
298
|
|
|
297
|
-
if not
|
|
299
|
+
if not confirm(f"\n [cyan]{i18n.t('cli.install.continue_install')}[/]", default=False):
|
|
298
300
|
break
|
|
299
301
|
|
|
300
302
|
def _install_adapters(self, remote_packages: dict, upgrade: bool, pre: bool):
|
|
@@ -341,7 +343,7 @@ class InstallCommand(Command):
|
|
|
341
343
|
|
|
342
344
|
selected_names = [name for name, _ in selected]
|
|
343
345
|
console.print(f"\n [dim]{i18n.t('cli.install.selected', selected=', '.join(selected_names))}[/]")
|
|
344
|
-
if
|
|
346
|
+
if confirm(
|
|
345
347
|
f" [cyan]{i18n.t('cli.install.confirm_adapters', count=len(selected_names))}[/]",
|
|
346
348
|
default=True,
|
|
347
349
|
):
|
|
@@ -390,7 +392,7 @@ class InstallCommand(Command):
|
|
|
390
392
|
|
|
391
393
|
selected_names = [name for name, _ in selected]
|
|
392
394
|
console.print(f"\n [dim]{i18n.t('cli.install.selected', selected=', '.join(selected_names))}[/]")
|
|
393
|
-
if
|
|
395
|
+
if confirm(
|
|
394
396
|
f" [cyan]{i18n.t('cli.install.confirm_modules', count=len(selected_names))}[/]",
|
|
395
397
|
default=True,
|
|
396
398
|
):
|
|
@@ -495,7 +497,7 @@ class InstallCommand(Command):
|
|
|
495
497
|
except ValueError:
|
|
496
498
|
continue
|
|
497
499
|
|
|
498
|
-
if selected and
|
|
500
|
+
if selected and confirm(
|
|
499
501
|
f" [cyan]{i18n.t('cli.install.confirm_search_install', count=len(selected))}[/]",
|
|
500
502
|
default=True,
|
|
501
503
|
):
|
|
@@ -514,7 +516,7 @@ class InstallCommand(Command):
|
|
|
514
516
|
if package_name.lower() == "q":
|
|
515
517
|
return
|
|
516
518
|
if package_name:
|
|
517
|
-
if
|
|
519
|
+
if confirm(
|
|
518
520
|
f" [cyan]{i18n.t('cli.install.confirm_custom_install', package_name=package_name)}[/]",
|
|
519
521
|
default=True,
|
|
520
522
|
):
|
|
@@ -534,6 +536,7 @@ class InstallCommand(Command):
|
|
|
534
536
|
"""
|
|
535
537
|
if not config_wizard.is_interactive():
|
|
536
538
|
console.print(f"[dim] {i18n.t('cli.install.configure_hint')}[/]")
|
|
539
|
+
console.print(f"[hint] {i18n.t('cli.install.done_hint')}[/]")
|
|
537
540
|
return
|
|
538
541
|
|
|
539
542
|
resolved = []
|
|
@@ -545,3 +548,4 @@ class InstallCommand(Command):
|
|
|
545
548
|
config_wizard.post_install_configure(resolved)
|
|
546
549
|
except Exception as e:
|
|
547
550
|
console.print(f"[warning] {i18n.t('cli.config.post_install_failed', error=e)}[/]")
|
|
551
|
+
console.print(f"[hint] {i18n.t('cli.install.done_hint')}[/]")
|