ErisPulse 2.7.1.dev4__tar.gz → 2.8.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.7.1.dev4 → erispulse-2.8.0.dev0}/PKG-INFO +2 -2
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/pyproject.toml +1 -1
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/commands/create.py +108 -11
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/commands/init.py +69 -26
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/commands/run.py +13 -3
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/constants.py +6 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/i18n/locales/en.py +5 -1
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/i18n/locales/ja.py +5 -1
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/i18n/locales/ru.py +5 -1
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/i18n/locales/zh_cn.py +5 -1
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/i18n/locales/zh_tw.py +5 -1
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/utils/scaffold_text.py +100 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Bases/__init__.py +8 -2
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Bases/adapter.py +36 -1
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Bases/client.py +5 -1
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Bases/module.py +130 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Event/base.py +48 -3
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Event/command.py +19 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/__init__.py +14 -5
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/adapter.py +420 -35
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/client.py +6 -2
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/constants.py +92 -2
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/i18n/locales/en.py +54 -4
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/i18n/locales/ja.py +54 -4
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/i18n/locales/ru.py +54 -4
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/i18n/locales/zh_cn.py +54 -4
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/i18n/locales/zh_tw.py +54 -4
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/lifecycle.py +17 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/logger.py +301 -23
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/module.py +549 -18
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/router.py +67 -3
- erispulse-2.8.0.dev0/src/ErisPulse/Core/scope.py +537 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/__init__.py +5 -2
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/loaders/adapter.py +8 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/loaders/module.py +732 -8
- erispulse-2.8.0.dev0/src/ErisPulse/loaders/plugin_folder.py +298 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/runtime/__init__.py +14 -1
- erispulse-2.8.0.dev0/src/ErisPulse/runtime/context.py +104 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/runtime/frame_config.py +32 -0
- erispulse-2.8.0.dev0/src/ErisPulse/runtime/plugin_reload.py +182 -0
- erispulse-2.8.0.dev0/src/ErisPulse/runtime/tasks.py +235 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/sdk.py +162 -8
- erispulse-2.7.1.dev4/src/ErisPulse/runtime/context.py +0 -51
- erispulse-2.7.1.dev4/src/ErisPulse/runtime/tasks.py +0 -109
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/.gitignore +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/LICENSE +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/README.pypi.md +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/__init__.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/base.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/cli.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/commands/__init__.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/commands/doctor.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/commands/install.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/commands/language.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/commands/list.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/commands/list_remote.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/commands/self_update.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/commands/types.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/commands/uninstall.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/commands/upgrade.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/console.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/hints.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/i18n/__init__.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/i18n/locales/__init__.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/registry.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/utils/__init__.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/utils/display.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/utils/file_watcher.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/CLI/utils/package_manager.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Bases/config_schema.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Bases/converter.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Bases/errors.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Bases/i18n_schema.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Bases/kv_builder.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Bases/manager.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Bases/router.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Bases/send_builder.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Bases/send_rules.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Bases/storage.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Bases/websocket.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Event/__init__.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Event/message.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Event/message_builder.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Event/meta.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Event/notice.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Event/request.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Event/session_type.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/Event/wrapper.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/assets/__init__.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/assets/error.css +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/assets/error.html +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/assets/root.css +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/assets/root.html +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/config.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/i18n/__init__.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/i18n/constants.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/i18n/locales/__init__.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/master.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/Core/storage.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/__main__.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/finders/__init__.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/finders/adapter.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/finders/bases/__init__.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/finders/bases/finder.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/finders/module.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/loaders/__init__.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/loaders/bases/__init__.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/loaders/bases/loader.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/loaders/strategy.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/loaders/strict.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/py.typed +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/runtime/config_schema.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/runtime/diagnostics.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/runtime/exceptions.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/runtime/hints.py +0 -0
- {erispulse-2.7.1.dev4 → erispulse-2.8.0.dev0}/src/ErisPulse/runtime/memory.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: ErisPulse
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.8.0.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.
|
|
7
|
+
version = "2.8.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"
|
|
@@ -64,8 +64,10 @@ _MODULE_INIT = """from .Core import Main
|
|
|
64
64
|
"""
|
|
65
65
|
|
|
66
66
|
_MODULE_CORE = """from dataclasses import dataclass, field
|
|
67
|
-
|
|
68
|
-
from ErisPulse
|
|
67
|
+
|
|
68
|
+
from ErisPulse import SDK
|
|
69
|
+
from ErisPulse.Core.Bases import BaseConfig, BaseI18n, BaseModule, I18nKey, ModuleMeta
|
|
70
|
+
from ErisPulse.Core.Event import Event, command, message, notice
|
|
69
71
|
from ErisPulse.Core.i18n import i18n
|
|
70
72
|
|
|
71
73
|
|
|
@@ -90,6 +92,15 @@ class Main(BaseModule):
|
|
|
90
92
|
class I18nClass(BaseI18n):
|
|
91
93
|
\"\"\"{name} translation keys\"\"\"
|
|
92
94
|
|
|
95
|
+
meta_description: I18nKey = I18nKey(
|
|
96
|
+
key=\"module.{name}.meta.description\",
|
|
97
|
+
default=\"{name} module\",
|
|
98
|
+
zh_CN=\"{name} 模块\",
|
|
99
|
+
en=\"{name} module\",
|
|
100
|
+
ja=\"{name} モジュール\",
|
|
101
|
+
ru=\"Модуль {name}\",
|
|
102
|
+
zh_TW=\"{name} 模組\",
|
|
103
|
+
)
|
|
93
104
|
enabled: I18nKey = I18nKey(
|
|
94
105
|
key=\"module.{name}.enabled\",
|
|
95
106
|
default=\"Enable module\",
|
|
@@ -118,22 +129,40 @@ class Main(BaseModule):
|
|
|
118
129
|
zh_TW=\"來自 {name} 的問候!\",
|
|
119
130
|
)
|
|
120
131
|
|
|
121
|
-
def __init__(self, sdk=None):
|
|
122
|
-
|
|
123
|
-
self.sdk =
|
|
132
|
+
def __init__(self, sdk: SDK = None):
|
|
133
|
+
# sdk 由框架在实例化时自动注入(无需手动导入兜底)
|
|
134
|
+
self.sdk = sdk
|
|
124
135
|
self.logger = self.sdk.logger.get_child(\"{name}\")
|
|
125
136
|
self.storage = self.sdk.storage
|
|
126
137
|
self.adapter = self.sdk.adapter
|
|
127
138
|
self.client = self.sdk.client
|
|
128
139
|
|
|
129
|
-
self.logger.info(
|
|
140
|
+
self.logger.info(\"{text[module.log.init_done]}\")
|
|
141
|
+
|
|
142
|
+
@staticmethod
|
|
143
|
+
def get_meta() -> ModuleMeta:
|
|
144
|
+
\"\"\"
|
|
145
|
+
{text[module.meta_doc]}
|
|
146
|
+
\"\"\"
|
|
147
|
+
return ModuleMeta(
|
|
148
|
+
name=\"{name}\",
|
|
149
|
+
# description 支持 i18n 字典(key 由 I18nClass 注册),也可用纯字符串
|
|
150
|
+
description={{\"i18n\": \"module.{name}.meta.description\", \"default\": \"{name} module\"}},
|
|
151
|
+
version=\"0.1.0\",
|
|
152
|
+
author=\"ErisDev\",
|
|
153
|
+
group=\"default\",
|
|
154
|
+
tags=[\"{name}\"],
|
|
155
|
+
)
|
|
130
156
|
|
|
131
157
|
@staticmethod
|
|
132
158
|
def get_load_strategy():
|
|
133
159
|
from ErisPulse.loaders import ModuleLoadStrategy
|
|
134
160
|
return ModuleLoadStrategy(
|
|
135
161
|
lazy_load=False,
|
|
136
|
-
priority=100
|
|
162
|
+
priority=100,
|
|
163
|
+
# 依赖声明(可选):缺失依赖的模块会被跳过加载;
|
|
164
|
+
# 被依赖模块卸载/热重载时,本模块将级联卸载/重载
|
|
165
|
+
# depends=[],
|
|
137
166
|
)
|
|
138
167
|
|
|
139
168
|
async def on_load(self, event: dict) -> bool:
|
|
@@ -164,20 +193,20 @@ class Main(BaseModule):
|
|
|
164
193
|
|
|
165
194
|
async def _register_commands(self):
|
|
166
195
|
@command(\"hello\", help=i18n.t(\"module.{name}.command.hello.help\"))
|
|
167
|
-
async def hello_command(event):
|
|
196
|
+
async def hello_command(event: Event):
|
|
168
197
|
await event.reply(i18n.t(\"module.{name}.command.hello.reply\"))
|
|
169
198
|
|
|
170
199
|
async def _register_message_handlers(self):
|
|
171
200
|
@message.on_private_message()
|
|
172
|
-
async def private_message_handler(event):
|
|
201
|
+
async def private_message_handler(event: Event):
|
|
173
202
|
self.logger.info((\"{text[module.log.private_message]}\").format(content=event.get_text()))
|
|
174
203
|
|
|
175
204
|
@message.on_group_message()
|
|
176
|
-
async def group_message_handler(event):
|
|
205
|
+
async def group_message_handler(event: Event):
|
|
177
206
|
pass
|
|
178
207
|
|
|
179
208
|
@notice.on_friend_add()
|
|
180
|
-
async def friend_add_handler(event):
|
|
209
|
+
async def friend_add_handler(event: Event):
|
|
181
210
|
self.logger.info((\"{text[module.log.friend_add]}\").format(nickname=event.get_user_nickname()))
|
|
182
211
|
"""
|
|
183
212
|
|
|
@@ -212,6 +241,7 @@ __all__ = [
|
|
|
212
241
|
_ADAPTER_CORE = """import asyncio
|
|
213
242
|
import json
|
|
214
243
|
from dataclasses import dataclass, field
|
|
244
|
+
from typing import ClassVar
|
|
215
245
|
from ErisPulse.Core import BaseAdapter
|
|
216
246
|
from ErisPulse.Core.Bases import BaseConfig, BaseI18n, I18nKey
|
|
217
247
|
from ErisPulse.Core import router
|
|
@@ -223,6 +253,13 @@ class {name}(BaseAdapter):
|
|
|
223
253
|
{text[adapter.doc]}
|
|
224
254
|
\"\"\"
|
|
225
255
|
|
|
256
|
+
# 依赖声明(可选,ErisPulse 2.8.0+):
|
|
257
|
+
# depends = {{"adapters": [], "modules": []}} # 硬依赖:缺失时跳过启动
|
|
258
|
+
# optional_modules = [] # 软依赖:就绪/丢失时收到
|
|
259
|
+
# # on_dependency_ready/lost 回调
|
|
260
|
+
depends: ClassVar[dict] = {{}}
|
|
261
|
+
optional_modules: ClassVar[list] = []
|
|
262
|
+
|
|
226
263
|
# {text[adapter.config_hint]}
|
|
227
264
|
@dataclass
|
|
228
265
|
class ConfigClass(BaseConfig):
|
|
@@ -645,6 +682,12 @@ class CreateCommand(Command):
|
|
|
645
682
|
parser.add_argument(
|
|
646
683
|
"--force", "-f", action="store_true", help=i18n.t("cli.create.force_help")
|
|
647
684
|
)
|
|
685
|
+
parser.add_argument(
|
|
686
|
+
"--local",
|
|
687
|
+
action="store_true",
|
|
688
|
+
default=False,
|
|
689
|
+
help=i18n.t("cli.create.local_module_help"),
|
|
690
|
+
)
|
|
648
691
|
|
|
649
692
|
def execute(self, args):
|
|
650
693
|
create_type = getattr(args, "create_type", None)
|
|
@@ -712,6 +755,11 @@ class CreateCommand(Command):
|
|
|
712
755
|
:param name: [str] 模块名称
|
|
713
756
|
:return: [None] 无返回值
|
|
714
757
|
"""
|
|
758
|
+
# --local:创建本地插件(plugins/ 目录结构,免打包安装)
|
|
759
|
+
if getattr(args, "local", False):
|
|
760
|
+
self._create_module_local(args, name)
|
|
761
|
+
return
|
|
762
|
+
|
|
715
763
|
description = self._ask_missing(
|
|
716
764
|
args,
|
|
717
765
|
"description",
|
|
@@ -797,6 +845,55 @@ class CreateCommand(Command):
|
|
|
797
845
|
console.print(f"[error] {i18n.t('cli.create.failed', error=e)}")
|
|
798
846
|
sys.exit(1)
|
|
799
847
|
|
|
848
|
+
def _create_module_local(self, args, name: str):
|
|
849
|
+
"""
|
|
850
|
+
创建本地插件(--local):生成 plugins/ 目录结构,免打包安装
|
|
851
|
+
|
|
852
|
+
:param args: [Any] 解析后的命令参数对象
|
|
853
|
+
:param name: [str] 模块名称
|
|
854
|
+
:return: [None] 无返回值
|
|
855
|
+
"""
|
|
856
|
+
output = Path(args.output)
|
|
857
|
+
plugins_dir = output / "plugins"
|
|
858
|
+
plugin_dir = plugins_dir / name
|
|
859
|
+
|
|
860
|
+
if plugin_dir.exists() and not args.force:
|
|
861
|
+
console.print(
|
|
862
|
+
f"[error] {i18n.t('cli.create.dir_exists', dir=str(plugin_dir))}"
|
|
863
|
+
)
|
|
864
|
+
sys.exit(1)
|
|
865
|
+
|
|
866
|
+
try:
|
|
867
|
+
plugin_dir.mkdir(parents=True, exist_ok=True)
|
|
868
|
+
|
|
869
|
+
(plugin_dir / "__init__.py").write_text(_MODULE_INIT, encoding="utf-8")
|
|
870
|
+
(plugin_dir / "Core.py").write_text(
|
|
871
|
+
_MODULE_CORE.format(name=name, text=_scaffold_text(name)),
|
|
872
|
+
encoding="utf-8",
|
|
873
|
+
)
|
|
874
|
+
|
|
875
|
+
console.print()
|
|
876
|
+
console.print(
|
|
877
|
+
f"[success] {i18n.t('cli.create.module_created', name=name)}[/]"
|
|
878
|
+
)
|
|
879
|
+
console.print()
|
|
880
|
+
console.print(Text(i18n.t("cli.create.local_structure"), style="bold"))
|
|
881
|
+
console.print(" plugins/")
|
|
882
|
+
console.print(f" └── {name}/")
|
|
883
|
+
console.print(" ├── __init__.py")
|
|
884
|
+
console.print(" └── Core.py")
|
|
885
|
+
console.print()
|
|
886
|
+
console.print(Text(i18n.t("cli.create.next_steps"), style="bold"))
|
|
887
|
+
console.print(f" · {i18n.t('cli.create.cd_to', dir=str(plugin_dir))}")
|
|
888
|
+
console.print(
|
|
889
|
+
f" · {i18n.t('cli.create.edit_module', file=str(plugin_dir) + '/Core.py')}"
|
|
890
|
+
)
|
|
891
|
+
console.print(f" · {i18n.t('cli.create.local_tip')}")
|
|
892
|
+
|
|
893
|
+
except Exception as e:
|
|
894
|
+
console.print(f"[error] {i18n.t('cli.create.failed', error=e)}")
|
|
895
|
+
sys.exit(1)
|
|
896
|
+
|
|
800
897
|
def _create_adapter(self, args, name: str):
|
|
801
898
|
"""
|
|
802
899
|
创建 Adapter 项目脚手架
|
|
@@ -124,6 +124,17 @@ class InitCommand(Command):
|
|
|
124
124
|
try:
|
|
125
125
|
for dir_name in ["config", "logs"]:
|
|
126
126
|
(project_path / dir_name).mkdir(exist_ok=True)
|
|
127
|
+
# SSL 证书默认目录:跟随项目运行目录走,配置里用相对路径引用
|
|
128
|
+
ssl_dir = project_path / "config" / "ssl"
|
|
129
|
+
ssl_dir.mkdir(exist_ok=True)
|
|
130
|
+
for ssl_name in ("cert.pem", "key.pem"):
|
|
131
|
+
ssl_file = ssl_dir / ssl_name
|
|
132
|
+
if not ssl_file.exists():
|
|
133
|
+
ssl_file.write_text(
|
|
134
|
+
"# 将你的证书/密钥 PEM 内容粘贴到本文件,"
|
|
135
|
+
"或在配置中改用 ssl_cert/ssl_key 内联填写\n",
|
|
136
|
+
encoding="utf-8",
|
|
137
|
+
)
|
|
127
138
|
|
|
128
139
|
config_file = project_path / "config" / "config.toml"
|
|
129
140
|
if not config_file.exists():
|
|
@@ -187,52 +198,84 @@ class InitCommand(Command):
|
|
|
187
198
|
"""
|
|
188
199
|
生成完整的配置示例文本
|
|
189
200
|
|
|
201
|
+
配置注释跟随 CLI 语言(缺失语言回退英文),
|
|
202
|
+
文案键集中于 ``scaffold_text`` 的 ``cfg.*`` 键族维护。
|
|
203
|
+
|
|
190
204
|
:param adapter_list: [list] 适配器名称列表 (默认: None)
|
|
191
205
|
:return: [str] 完整配置示例字符串
|
|
192
206
|
"""
|
|
207
|
+
from ..utils.scaffold_text import ScaffoldText
|
|
208
|
+
|
|
209
|
+
st = ScaffoldText()
|
|
193
210
|
lines = [
|
|
194
|
-
"
|
|
195
|
-
"
|
|
196
|
-
"
|
|
211
|
+
st.t("cfg.header.title"),
|
|
212
|
+
st.t("cfg.header.desc"),
|
|
213
|
+
st.t("cfg.header.usage"),
|
|
197
214
|
"",
|
|
198
|
-
"
|
|
215
|
+
st.t("cfg.section.server"),
|
|
199
216
|
"",
|
|
200
217
|
"[ErisPulse.server]",
|
|
201
|
-
'host = "0.0.0.0" #
|
|
202
|
-
"port = 8000 #
|
|
203
|
-
"auto_start = true #
|
|
204
|
-
|
|
205
|
-
|
|
218
|
+
f'host = "0.0.0.0" # {st.t("cfg.server.host")}',
|
|
219
|
+
f"port = 8000 # {st.t('cfg.server.port')}",
|
|
220
|
+
f"auto_start = true # {st.t('cfg.server.auto_start')}",
|
|
221
|
+
f'ssl_certfile = "config/ssl/cert.pem" # {st.t("cfg.server.ssl_certfile")}',
|
|
222
|
+
f'ssl_keyfile = "config/ssl/key.pem" # {st.t("cfg.server.ssl_keyfile")}',
|
|
223
|
+
st.t("cfg.server.ssl_inline_hint"),
|
|
224
|
+
'# ssl_cert = """-----BEGIN CERTIFICATE-----',
|
|
225
|
+
"# ...",
|
|
226
|
+
'# -----END CERTIFICATE-----"""',
|
|
227
|
+
'# ssl_key = """-----BEGIN PRIVATE KEY-----',
|
|
228
|
+
"# ...",
|
|
229
|
+
'# -----END PRIVATE KEY-----"""',
|
|
206
230
|
"",
|
|
207
|
-
"
|
|
231
|
+
st.t("cfg.section.logger"),
|
|
208
232
|
"",
|
|
209
233
|
"[ErisPulse.logger]",
|
|
210
|
-
'level = "INFO" #
|
|
211
|
-
|
|
212
|
-
|
|
234
|
+
f'level = "INFO" # {st.t("cfg.logger.level")}',
|
|
235
|
+
f"log_files = [] # {st.t('cfg.logger.log_files')}",
|
|
236
|
+
f'log_dir = "" # {st.t("cfg.logger.log_dir")}',
|
|
237
|
+
f'log_rotation = "size" # {st.t("cfg.logger.log_rotation")}',
|
|
238
|
+
f"log_max_size_mb = 10 # {st.t('cfg.logger.log_max_size_mb')}",
|
|
239
|
+
f"log_backup_count = 5 # {st.t('cfg.logger.log_backup_count')}",
|
|
240
|
+
f'log_rotation_when = "midnight" # {st.t("cfg.logger.log_rotation_when")}',
|
|
241
|
+
f"memory_limit = 1000 # {st.t('cfg.logger.memory_limit')}",
|
|
213
242
|
"",
|
|
214
|
-
"
|
|
243
|
+
st.t("cfg.section.storage"),
|
|
215
244
|
"",
|
|
216
245
|
"[ErisPulse.storage]",
|
|
217
|
-
"use_global_db = false #
|
|
246
|
+
f"use_global_db = false # {st.t('cfg.storage.use_global_db')}",
|
|
218
247
|
"",
|
|
219
|
-
"
|
|
248
|
+
st.t("cfg.section.event"),
|
|
220
249
|
"",
|
|
221
250
|
"[ErisPulse.event.message]",
|
|
222
|
-
"ignore_self = true #
|
|
251
|
+
f"ignore_self = true # {st.t('cfg.event.ignore_self')}",
|
|
223
252
|
"",
|
|
224
253
|
"[ErisPulse.event.command]",
|
|
225
|
-
'prefix = "/" #
|
|
226
|
-
"case_sensitive = true #
|
|
227
|
-
"allow_space_prefix = false #
|
|
228
|
-
"must_at_bot = false #
|
|
254
|
+
f'prefix = "/" # {st.t("cfg.command.prefix")}',
|
|
255
|
+
f"case_sensitive = true # {st.t('cfg.command.case_sensitive')}",
|
|
256
|
+
f"allow_space_prefix = false # {st.t('cfg.command.allow_space_prefix')}",
|
|
257
|
+
f"must_at_bot = false # {st.t('cfg.command.must_at_bot')}",
|
|
229
258
|
"",
|
|
230
|
-
"
|
|
259
|
+
st.t("cfg.section.framework"),
|
|
231
260
|
"",
|
|
232
261
|
"[ErisPulse.framework]",
|
|
233
|
-
"enable_lazy_loading = true
|
|
262
|
+
f"enable_lazy_loading = true # {st.t('cfg.framework.enable_lazy_loading')}",
|
|
263
|
+
f'plugins_dir = "plugins" # {st.t("cfg.framework.plugins_dir")}',
|
|
264
|
+
f"uninit_timeout = 30 # {st.t('cfg.framework.uninit_timeout')}",
|
|
265
|
+
f" {st.t('cfg.framework.uninit_timeout_line1')}",
|
|
266
|
+
f" {st.t('cfg.framework.uninit_timeout_line2')}",
|
|
267
|
+
f"strict_mode = false # {st.t('cfg.framework.strict_mode')}",
|
|
268
|
+
f"strict_mode_exceptions = {{ modules = [], adapters = [] }} # {st.t('cfg.framework.strict_mode_exceptions')}",
|
|
269
|
+
f"handler_max_concurrency = 64 # {st.t('cfg.framework.handler_max_concurrency')}",
|
|
270
|
+
f"proactive_gc_interval = 300 # {st.t('cfg.framework.proactive_gc_interval')}",
|
|
271
|
+
f"proactive_gc_generation = 2 # {st.t('cfg.framework.proactive_gc_generation')}",
|
|
272
|
+
f"proactive_gc_full_every = 10 # {st.t('cfg.framework.proactive_gc_full_every')}",
|
|
273
|
+
f"proactive_gc_memory_growth_mb = 100 # {st.t('cfg.framework.proactive_gc_memory_growth_mb')}",
|
|
274
|
+
f"proactive_gc_idle_only = true # {st.t('cfg.framework.proactive_gc_idle_only')}",
|
|
275
|
+
f"proactive_gc_gen0_min = 100 # {st.t('cfg.framework.proactive_gc_gen0_min')}",
|
|
276
|
+
f"offline_bot_expiry = 3600 # {st.t('cfg.framework.offline_bot_expiry')}",
|
|
234
277
|
"",
|
|
235
|
-
"
|
|
278
|
+
st.t("cfg.section.router"),
|
|
236
279
|
"",
|
|
237
280
|
"[ErisPulse.router.cors]",
|
|
238
281
|
"enabled = false",
|
|
@@ -249,7 +292,7 @@ class InitCommand(Command):
|
|
|
249
292
|
'X-Content-Type-Options = "nosniff"',
|
|
250
293
|
'X-Frame-Options = "DENY"',
|
|
251
294
|
"",
|
|
252
|
-
"
|
|
295
|
+
st.t("cfg.section.adapter_status"),
|
|
253
296
|
"",
|
|
254
297
|
"[ErisPulse.adapters.status]",
|
|
255
298
|
]
|
|
@@ -268,7 +311,7 @@ class InitCommand(Command):
|
|
|
268
311
|
lines.extend(
|
|
269
312
|
[
|
|
270
313
|
"",
|
|
271
|
-
"
|
|
314
|
+
st.t("cfg.section.module_status"),
|
|
272
315
|
"",
|
|
273
316
|
"[ErisPulse.modules.status]",
|
|
274
317
|
"# MyModule = true",
|
|
@@ -5,6 +5,7 @@ Run 命令实现
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import asyncio
|
|
8
|
+
import os
|
|
8
9
|
import runpy
|
|
9
10
|
import subprocess
|
|
10
11
|
import sys
|
|
@@ -17,7 +18,7 @@ from rich.panel import Panel
|
|
|
17
18
|
|
|
18
19
|
from ..base import Command
|
|
19
20
|
from ..console import console
|
|
20
|
-
from ..constants import HARD_RESTART_EXIT_CODE
|
|
21
|
+
from ..constants import ENV_SUPERVISED, HARD_RESTART_EXIT_CODE
|
|
21
22
|
from ..i18n import i18n
|
|
22
23
|
from ..utils.file_watcher import FileSystemEventHandler, PollingObserver
|
|
23
24
|
|
|
@@ -186,7 +187,11 @@ class RunCommand(Command):
|
|
|
186
187
|
process = None
|
|
187
188
|
try:
|
|
188
189
|
while True:
|
|
189
|
-
|
|
190
|
+
# 注入监督者标记:子进程据此判断"有父进程会在退出码 42 时重新拉起我",
|
|
191
|
+
# 从而 hard_restart() 走退出码契约而非 self-respawn。
|
|
192
|
+
child_env = dict(os.environ)
|
|
193
|
+
child_env[ENV_SUPERVISED] = "cli"
|
|
194
|
+
process = subprocess.Popen(cmd, env=child_env)
|
|
190
195
|
process.wait()
|
|
191
196
|
|
|
192
197
|
if process.returncode == self._RESTART_EXIT_CODE:
|
|
@@ -195,7 +200,12 @@ class RunCommand(Command):
|
|
|
195
200
|
time.sleep(0.5)
|
|
196
201
|
continue
|
|
197
202
|
|
|
198
|
-
|
|
203
|
+
if process.returncode == 0:
|
|
204
|
+
# 子进程正常退出:finish,不再拉起
|
|
205
|
+
console.print(f"[info]{i18n.t('cli.run.process_exited')}[/]")
|
|
206
|
+
break
|
|
207
|
+
|
|
208
|
+
# 非硬重启/非正常退出码:模块/适配器内部错误导致子进程异常终止
|
|
199
209
|
# 不退出主进程,等待后自动重试
|
|
200
210
|
crash_count += 1
|
|
201
211
|
backoff = min(self._MAX_CRASH_BACKOFF, 3.0 * crash_count)
|
|
@@ -23,6 +23,11 @@ StorageManager 等单例)。因此 CLI 需要的常量在此独立维护,**
|
|
|
23
23
|
# 镜像于: ErisPulse.Core.constants.HARD_RESTART_EXIT_CODE
|
|
24
24
|
HARD_RESTART_EXIT_CODE: int = 42
|
|
25
25
|
|
|
26
|
+
# 监督者标记环境变量名。
|
|
27
|
+
# CLI run 命令启动子进程时注入;SDK 据此判断是否被监督(决定硬重启是否会被拉起)。
|
|
28
|
+
# 镜像于: ErisPulse.Core.constants.ENV_SUPERVISED
|
|
29
|
+
ENV_SUPERVISED: str = "ERISPULSE_SUPERVISED"
|
|
30
|
+
|
|
26
31
|
# 模块入口点组名(loader / finder / create / types 共用)。
|
|
27
32
|
# 镜像于: ErisPulse.Core.constants.MODULE_ENTRY_POINT_GROUP
|
|
28
33
|
MODULE_ENTRY_POINT_GROUP: str = "erispulse.module"
|
|
@@ -40,6 +45,7 @@ PYPI_PACKAGE_JSON_URL_TEMPLATE: str = "https://pypi.org/pypi/{package}/json"
|
|
|
40
45
|
|
|
41
46
|
__all__ = [
|
|
42
47
|
"ADAPTER_ENTRY_POINT_GROUP",
|
|
48
|
+
"ENV_SUPERVISED",
|
|
43
49
|
"HARD_RESTART_EXIT_CODE",
|
|
44
50
|
"MODULE_ENTRY_POINT_GROUP",
|
|
45
51
|
"PYPI_PACKAGE_JSON_URL_TEMPLATE",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
2
|
CLI English translations (en)
|
|
3
3
|
|
|
4
4
|
Independent CLI translation data, decoupled from Core i18n.
|
|
@@ -48,6 +48,9 @@ TRANSLATIONS = {
|
|
|
48
48
|
"cli.create.homepage_help": "Project homepage URL",
|
|
49
49
|
"cli.create.output_help": "Output directory (default: current directory)",
|
|
50
50
|
"cli.create.force_help": "Force overwrite existing directory",
|
|
51
|
+
"cli.create.local_module_help": "Create a local plugin (plugins/ structure, no packaging/install; module only)",
|
|
52
|
+
"cli.create.local_structure": "Local plugin structure",
|
|
53
|
+
"cli.create.local_tip": "Place the plugin in the project's plugins/ directory; auto-discovered on startup and hot-reloaded on change",
|
|
51
54
|
"cli.create.select_type_title": "Select creation type",
|
|
52
55
|
"cli.create.select_type_module": "Custom functional Module",
|
|
53
56
|
"cli.create.select_type_adapter": "Platform Adapter",
|
|
@@ -276,6 +279,7 @@ TRANSLATIONS = {
|
|
|
276
279
|
"cli.run.file_changed_restart": "File change detected ([cmd]{file}[/]), restarting...",
|
|
277
280
|
"cli.run.process_exited": "Process exited normally, waiting for file changes to restart",
|
|
278
281
|
"cli.run.process_crashed": "Process crashed (exit code {code}), fix and save to restart",
|
|
282
|
+
"cli.run.process_exited": "Child process exited normally, not respawning",
|
|
279
283
|
"cli.run.subprocess_crashed_retry": "Subprocess crashed, will auto-retry in {seconds}s...",
|
|
280
284
|
"cli.run.terminating_child": "Terminating the bot subprocess to release ports and resources...",
|
|
281
285
|
# ==================== uninstall command ====================
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
2
|
CLI 日本語翻訳 (ja)
|
|
3
3
|
|
|
4
4
|
Core i18n から独立した CLI 翻訳データ。
|
|
@@ -48,6 +48,9 @@ TRANSLATIONS = {
|
|
|
48
48
|
"cli.create.homepage_help": "プロジェクトのホームページ URL",
|
|
49
49
|
"cli.create.output_help": "出力ディレクトリ (デフォルト: カレントディレクトリ)",
|
|
50
50
|
"cli.create.force_help": "既存のディレクトリを強制的に上書き",
|
|
51
|
+
"cli.create.local_module_help": "ローカルプラグインを作成(plugins/ 構造、パッケージ不要。module のみ)",
|
|
52
|
+
"cli.create.local_structure": "ローカルプラグイン構造",
|
|
53
|
+
"cli.create.local_tip": "プラグインをプロジェクトの plugins/ ディレクトリに配置すると起動時に自動検出され、変更時はホットリロードされます",
|
|
51
54
|
"cli.create.select_type_title": "作成タイプを選択",
|
|
52
55
|
"cli.create.select_type_module": "カスタム機能 Module",
|
|
53
56
|
"cli.create.select_type_adapter": "プラットフォーム Adapter",
|
|
@@ -276,6 +279,7 @@ TRANSLATIONS = {
|
|
|
276
279
|
"cli.run.file_changed_restart": "ファイル変更を検出 ([cmd]{file}[/])、再起動中...",
|
|
277
280
|
"cli.run.process_exited": "プロセスが正常に終了しました。ファイルの変更を待機して再起動",
|
|
278
281
|
"cli.run.process_crashed": "プロセスが異常終了しました(終了コード {code})。修正して保存すると自動再起動",
|
|
282
|
+
"cli.run.process_exited": "子プロセスが正常終了しました、再起動しません",
|
|
279
283
|
"cli.run.subprocess_crashed_retry": "サブプロセスが異常終了しました。{seconds} 秒後に自動再試行します...",
|
|
280
284
|
"cli.run.terminating_child": "ポートなどのリソースを解放するため、ボットの子プロセスを終了しています...",
|
|
281
285
|
# ==================== uninstall コマンド ====================
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
2
|
CLI Русский перевод (ru)
|
|
3
3
|
|
|
4
4
|
Независимые переводы CLI, отдельно от Core i18n.
|
|
@@ -48,6 +48,9 @@ TRANSLATIONS = {
|
|
|
48
48
|
"cli.create.homepage_help": "URL домашней страницы проекта",
|
|
49
49
|
"cli.create.output_help": "Выходной каталог (по умолчанию: текущий каталог)",
|
|
50
50
|
"cli.create.force_help": "Принудительно перезаписать существующий каталог",
|
|
51
|
+
"cli.create.local_module_help": "Создать локальный плагин (структура plugins/, без упаковки и установки; только для module)",
|
|
52
|
+
"cli.create.local_structure": "Структура локального плагина",
|
|
53
|
+
"cli.create.local_tip": "Поместите плагин в каталог plugins/ проекта — он будет автоматически обнаружен при запуске и перезагружен при изменении",
|
|
51
54
|
"cli.create.select_type_title": "Выберите тип создания",
|
|
52
55
|
"cli.create.select_type_module": "Пользовательский функциональный Module",
|
|
53
56
|
"cli.create.select_type_adapter": "Платформенный Adapter",
|
|
@@ -276,6 +279,7 @@ TRANSLATIONS = {
|
|
|
276
279
|
"cli.run.file_changed_restart": "Обнаружено изменение файла ([cmd]{file}[/]), перезапуск...",
|
|
277
280
|
"cli.run.process_exited": "Процесс завершен нормально, ожидание изменений файлов для перезапуска",
|
|
278
281
|
"cli.run.process_crashed": "Процесс аварийно завершен (код {code}), исправьте и сохраните для перезапуска",
|
|
282
|
+
"cli.run.process_exited": "Дочерний процесс завершился нормально, не перезапускаем",
|
|
279
283
|
"cli.run.subprocess_crashed_retry": "Подпроцесс аварийно завершен, автоматическая перезагрузка через {seconds}с...",
|
|
280
284
|
"cli.run.terminating_child": "Завершение дочернего процесса бота для освобождения портов и ресурсов...",
|
|
281
285
|
# ==================== команда uninstall ====================
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
2
|
CLI 简体中文翻译 (zh-CN)
|
|
3
3
|
|
|
4
4
|
独立于 Core i18n 的 CLI 翻译数据。
|
|
@@ -48,6 +48,9 @@ TRANSLATIONS = {
|
|
|
48
48
|
"cli.create.homepage_help": "项目主页 URL",
|
|
49
49
|
"cli.create.output_help": "输出目录 (默认当前目录)",
|
|
50
50
|
"cli.create.force_help": "强制覆盖已存在的目录",
|
|
51
|
+
"cli.create.local_module_help": "创建本地插件(plugins/ 目录结构,免打包安装,仅 module 可用)",
|
|
52
|
+
"cli.create.local_structure": "本地插件结构",
|
|
53
|
+
"cli.create.local_tip": "将插件放入项目的 plugins/ 目录,框架启动时自动发现;修改后热重载自动生效",
|
|
51
54
|
"cli.create.select_type_title": "选择创建类型",
|
|
52
55
|
"cli.create.select_type_module": "自定义功能模块",
|
|
53
56
|
"cli.create.select_type_adapter": "平台适配器",
|
|
@@ -276,6 +279,7 @@ TRANSLATIONS = {
|
|
|
276
279
|
"cli.run.file_changed_restart": "检测到文件变更 ([cmd]{file}[/]),正在重启...",
|
|
277
280
|
"cli.run.process_exited": "进程已正常退出,等待文件变更后重启",
|
|
278
281
|
"cli.run.process_crashed": "进程异常退出(退出码 {code}),修复后保存文件将自动重启",
|
|
282
|
+
"cli.run.process_exited": "子进程正常退出,不再拉起",
|
|
279
283
|
"cli.run.subprocess_crashed_retry": "子进程异常终止,将在 {seconds} 秒后自动重试...",
|
|
280
284
|
"cli.run.terminating_child": "正在终止机器人子进程,释放端口等资源...",
|
|
281
285
|
# ==================== uninstall 命令 ====================
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
2
|
CLI 繁體中文翻譯 (zh-TW)
|
|
3
3
|
|
|
4
4
|
獨立于 Core i18n 的 CLI 翻譯資料。
|
|
@@ -48,6 +48,9 @@ TRANSLATIONS = {
|
|
|
48
48
|
"cli.create.homepage_help": "專案首頁 URL",
|
|
49
49
|
"cli.create.output_help": "輸出目錄 (預設為當前目錄)",
|
|
50
50
|
"cli.create.force_help": "強制覆蓋已存在的目錄",
|
|
51
|
+
"cli.create.local_module_help": "建立本地外掛(plugins/ 目錄結構,免打包安裝,僅 module 可用)",
|
|
52
|
+
"cli.create.local_structure": "本地外掛結構",
|
|
53
|
+
"cli.create.local_tip": "將外掛放入專案的 plugins/ 目錄,框架啟動時自動發現;修改後熱重載自動生效",
|
|
51
54
|
"cli.create.select_type_title": "選擇建立類型",
|
|
52
55
|
"cli.create.select_type_module": "自訂功能 Module",
|
|
53
56
|
"cli.create.select_type_adapter": "平台 Adapter",
|
|
@@ -276,6 +279,7 @@ TRANSLATIONS = {
|
|
|
276
279
|
"cli.run.file_changed_restart": "檢測到檔案變更 ([cmd]{file}[/]),正在重啟...",
|
|
277
280
|
"cli.run.process_exited": "程式已正常退出,等待檔案變更後重啟",
|
|
278
281
|
"cli.run.process_crashed": "程式異常退出(退出碼 {code}),修復後儲存檔案將自動重啟",
|
|
282
|
+
"cli.run.process_exited": "子程序正常退出,不再拉起",
|
|
279
283
|
"cli.run.subprocess_crashed_retry": "子程序異常終止,將在 {seconds} 秒後自動重試...",
|
|
280
284
|
"cli.run.terminating_child": "正在終止機器人子程序,釋放連接埠等資源...",
|
|
281
285
|
# ==================== uninstall 命令 ====================
|