ErisPulse 2.7.1.dev0__tar.gz → 2.7.1.dev1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/PKG-INFO +1 -1
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/pyproject.toml +1 -1
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/commands/doctor.py +67 -10
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/commands/list.py +3 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/i18n/locales/en.py +3 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/i18n/locales/ja.py +3 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/i18n/locales/ru.py +3 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/i18n/locales/zh_cn.py +3 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/i18n/locales/zh_tw.py +3 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/utils/display.py +4 -1
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Event/base.py +9 -1
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/adapter.py +25 -11
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/config.py +29 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/constants.py +7 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/i18n/locales/en.py +40 -2
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/i18n/locales/ja.py +40 -2
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/i18n/locales/ru.py +40 -2
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/i18n/locales/zh_cn.py +40 -2
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/i18n/locales/zh_tw.py +40 -2
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/logger.py +181 -30
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/module.py +33 -4
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/router.py +80 -3
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/finders/bases/finder.py +46 -9
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/loaders/adapter.py +8 -3
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/loaders/bases/loader.py +18 -6
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/loaders/module.py +98 -29
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/loaders/strict.py +32 -2
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/runtime/exceptions.py +58 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/runtime/frame_config.py +48 -5
- erispulse-2.7.1.dev1/src/ErisPulse/runtime/tasks.py +109 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/sdk.py +34 -0
- erispulse-2.7.1.dev0/src/ErisPulse/runtime/tasks.py +0 -63
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/.gitignore +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/LICENSE +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/README.pypi.md +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/__init__.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/base.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/cli.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/commands/__init__.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/commands/create.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/commands/init.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/commands/install.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/commands/language.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/commands/list_remote.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/commands/run.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/commands/self_update.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/commands/types.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/commands/uninstall.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/commands/upgrade.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/console.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/constants.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/hints.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/i18n/__init__.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/i18n/locales/__init__.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/registry.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/utils/__init__.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/utils/file_watcher.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/utils/package_manager.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/CLI/utils/scaffold_text.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Bases/__init__.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Bases/adapter.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Bases/client.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Bases/config_schema.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Bases/converter.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Bases/errors.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Bases/i18n_schema.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Bases/kv_builder.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Bases/manager.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Bases/module.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Bases/router.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Bases/send_builder.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Bases/send_rules.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Bases/storage.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Bases/websocket.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Event/__init__.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Event/command.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Event/message.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Event/message_builder.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Event/meta.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Event/notice.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Event/request.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Event/session_type.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/Event/wrapper.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/__init__.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/assets/__init__.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/assets/error.css +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/assets/error.html +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/assets/root.css +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/assets/root.html +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/client.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/i18n/__init__.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/i18n/constants.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/i18n/locales/__init__.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/lifecycle.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/master.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/Core/storage.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/__init__.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/__main__.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/finders/__init__.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/finders/adapter.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/finders/bases/__init__.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/finders/module.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/loaders/__init__.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/loaders/bases/__init__.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/loaders/strategy.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/py.typed +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/runtime/__init__.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/runtime/config_schema.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/runtime/context.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/runtime/diagnostics.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/runtime/hints.py +0 -0
- {erispulse-2.7.1.dev0 → erispulse-2.7.1.dev1}/src/ErisPulse/runtime/memory.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ErisPulse
|
|
3
|
-
Version: 2.7.1.
|
|
3
|
+
Version: 2.7.1.dev1
|
|
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.1-dev.
|
|
7
|
+
version = "2.7.1-dev.1"
|
|
8
8
|
description = "Event-driven modular async bot framework — write once, deploy to any platform | 事件驱动的模块化异步机器人框架,一次编写,多平台部署"
|
|
9
9
|
readme = "README.pypi.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -43,13 +43,14 @@ class DoctorCommand(Command):
|
|
|
43
43
|
|
|
44
44
|
def execute(self, args):
|
|
45
45
|
pm = self.package_manager
|
|
46
|
-
rows: list[tuple[str, str]] = []
|
|
46
|
+
rows: list[tuple[str, str, str]] = []
|
|
47
47
|
failed = False
|
|
48
48
|
|
|
49
49
|
# 1. Python 解释器
|
|
50
50
|
py_ok = sys.version_info >= (3, 10)
|
|
51
51
|
rows.append(
|
|
52
52
|
(
|
|
53
|
+
self._status(py_ok),
|
|
53
54
|
i18n.t("cli.doctor.python"),
|
|
54
55
|
f"{platform.python_version()} ({sys.executable})",
|
|
55
56
|
)
|
|
@@ -60,27 +61,43 @@ class DoctorCommand(Command):
|
|
|
60
61
|
# 2. 安装后端(uv / pip)
|
|
61
62
|
uv_cmd = pm._get_uv_command()
|
|
62
63
|
if uv_cmd:
|
|
63
|
-
rows.append(
|
|
64
|
+
rows.append(
|
|
65
|
+
(self._status(True), i18n.t("cli.doctor.backend"), f"uv ({uv_cmd[0]})")
|
|
66
|
+
)
|
|
64
67
|
else:
|
|
65
|
-
rows.append(
|
|
68
|
+
rows.append(
|
|
69
|
+
(
|
|
70
|
+
self._status(True),
|
|
71
|
+
i18n.t("cli.doctor.backend"),
|
|
72
|
+
i18n.t("cli.doctor.backend_pip"),
|
|
73
|
+
)
|
|
74
|
+
)
|
|
66
75
|
|
|
67
76
|
# 3. 目标解释器(安装目标环境)
|
|
68
77
|
target_python = pm._get_target_python()
|
|
69
|
-
rows.append(
|
|
78
|
+
rows.append(
|
|
79
|
+
(self._status(True), i18n.t("cli.doctor.target_python"), target_python)
|
|
80
|
+
)
|
|
70
81
|
|
|
71
82
|
# 4. 配置文件
|
|
72
83
|
config_path = Path("config") / "config.toml"
|
|
73
84
|
if config_path.exists():
|
|
74
85
|
rows.append(
|
|
75
|
-
(
|
|
86
|
+
(
|
|
87
|
+
self._status(True),
|
|
88
|
+
i18n.t("cli.doctor.config"),
|
|
89
|
+
str(config_path.resolve()),
|
|
90
|
+
)
|
|
76
91
|
)
|
|
77
92
|
else:
|
|
78
93
|
rows.append(
|
|
79
94
|
(
|
|
95
|
+
self._status(False),
|
|
80
96
|
i18n.t("cli.doctor.config"),
|
|
81
97
|
f"{i18n.t('cli.doctor.config_missing')} ({config_path})",
|
|
82
98
|
)
|
|
83
99
|
)
|
|
100
|
+
failed = True
|
|
84
101
|
|
|
85
102
|
# 5. PyPI 连通性
|
|
86
103
|
try:
|
|
@@ -90,21 +107,40 @@ class DoctorCommand(Command):
|
|
|
90
107
|
)
|
|
91
108
|
rows.append(
|
|
92
109
|
(
|
|
110
|
+
self._status(True),
|
|
93
111
|
i18n.t("cli.doctor.pypi"),
|
|
94
112
|
i18n.t("cli.doctor.pypi_ok", count=pkg_count),
|
|
95
113
|
)
|
|
96
114
|
)
|
|
97
115
|
except Exception:
|
|
98
116
|
failed = True
|
|
99
|
-
rows.append(
|
|
117
|
+
rows.append(
|
|
118
|
+
(
|
|
119
|
+
self._status(False),
|
|
120
|
+
i18n.t("cli.doctor.pypi"),
|
|
121
|
+
i18n.t("cli.doctor.pypi_fail"),
|
|
122
|
+
)
|
|
123
|
+
)
|
|
100
124
|
|
|
101
125
|
# 6. 代理
|
|
102
126
|
proxy = pm._get_system_proxy()
|
|
103
127
|
if proxy:
|
|
104
128
|
https_proxy = proxy.get("https") or proxy.get("http", "")
|
|
105
|
-
rows.append(
|
|
129
|
+
rows.append(
|
|
130
|
+
(
|
|
131
|
+
self._status(True),
|
|
132
|
+
i18n.t("cli.doctor.proxy"),
|
|
133
|
+
https_proxy,
|
|
134
|
+
)
|
|
135
|
+
)
|
|
106
136
|
else:
|
|
107
|
-
rows.append(
|
|
137
|
+
rows.append(
|
|
138
|
+
(
|
|
139
|
+
self._status(True),
|
|
140
|
+
i18n.t("cli.doctor.proxy"),
|
|
141
|
+
i18n.t("cli.doctor.proxy_none"),
|
|
142
|
+
)
|
|
143
|
+
)
|
|
108
144
|
|
|
109
145
|
# 输出诊断报告
|
|
110
146
|
table = Table(
|
|
@@ -113,15 +149,36 @@ class DoctorCommand(Command):
|
|
|
113
149
|
pad_edge=False,
|
|
114
150
|
expand=True,
|
|
115
151
|
)
|
|
116
|
-
for label, detail in rows:
|
|
117
|
-
table.add_row(f"[info]{label}[/]", detail)
|
|
152
|
+
for status, label, detail in rows:
|
|
153
|
+
table.add_row(status, f"[info]{label}[/]", detail)
|
|
118
154
|
|
|
119
155
|
console.print(table)
|
|
120
156
|
|
|
121
157
|
if failed:
|
|
122
158
|
console.print(f"[error]{i18n.t('cli.doctor.failed')}[/]")
|
|
159
|
+
for status, label, _ in rows:
|
|
160
|
+
if status != self._status(True):
|
|
161
|
+
console.print(
|
|
162
|
+
f" [error]-[/] [info]{label}[/]"
|
|
163
|
+
)
|
|
123
164
|
else:
|
|
124
165
|
console.print(f"[success]{i18n.t('cli.doctor.all_ok')}[/]")
|
|
125
166
|
|
|
167
|
+
@staticmethod
|
|
168
|
+
def _status(ok: bool) -> str:
|
|
169
|
+
"""
|
|
170
|
+
生成诊断项的状态标记文本(OK / FAIL,不使用 emoji)
|
|
171
|
+
|
|
172
|
+
:param ok: bool 诊断项是否正常
|
|
173
|
+
:return: str 带样式的状态标记文本
|
|
174
|
+
"""
|
|
175
|
+
from ..i18n import i18n
|
|
176
|
+
|
|
177
|
+
return (
|
|
178
|
+
f"[success]{i18n.t('cli.doctor.status_ok')}[/]"
|
|
179
|
+
if ok
|
|
180
|
+
else f"[error]{i18n.t('cli.doctor.status_fail')}[/]"
|
|
181
|
+
)
|
|
182
|
+
|
|
126
183
|
|
|
127
184
|
__all__ = ["DoctorCommand"]
|
|
@@ -121,6 +121,7 @@ class ListCommand(Command):
|
|
|
121
121
|
self._print_package_scripts(installed["modules"])
|
|
122
122
|
else:
|
|
123
123
|
console.print(f"[dim] {i18n.t('cli.list.no_modules')}[/]")
|
|
124
|
+
console.print(f"[dim] {i18n.t('cli.list.empty_hint')}[/]")
|
|
124
125
|
|
|
125
126
|
elif pkg_type == "adapters" and installed["adapters"]:
|
|
126
127
|
table = Table(
|
|
@@ -154,11 +155,13 @@ class ListCommand(Command):
|
|
|
154
155
|
)
|
|
155
156
|
else:
|
|
156
157
|
console.print(f"[dim] {i18n.t('cli.list.no_adapters')}[/]")
|
|
158
|
+
console.print(f"[dim] {i18n.t('cli.list.empty_hint')}[/]")
|
|
157
159
|
|
|
158
160
|
elif not installed.get(pkg_type, {}):
|
|
159
161
|
console.print(
|
|
160
162
|
f"[dim] {i18n.t('cli.list.no_packages', pkg_type=pkg_type)}[/]"
|
|
161
163
|
)
|
|
164
|
+
console.print(f"[dim] {i18n.t('cli.list.empty_hint')}[/]")
|
|
162
165
|
|
|
163
166
|
def _is_package_outdated(
|
|
164
167
|
self,
|
|
@@ -205,6 +205,7 @@ TRANSLATIONS = {
|
|
|
205
205
|
"cli.list.count_adapters": "{count} adapter(s)",
|
|
206
206
|
"cli.list.no_adapters": "No matching adapters",
|
|
207
207
|
"cli.list.no_packages": "No {pkg_type}",
|
|
208
|
+
"cli.list.empty_hint": "Run 'epsdk install' to browse and install components, or 'epsdk init' to create a project",
|
|
208
209
|
# ==================== list-remote command ====================
|
|
209
210
|
"cli.list_remote.description": "List remote available components",
|
|
210
211
|
"cli.list_remote.type_help": "List type (default: all)",
|
|
@@ -416,6 +417,8 @@ TRANSLATIONS = {
|
|
|
416
417
|
"cli.doctor.proxy_none": "none detected",
|
|
417
418
|
"cli.doctor.failed": "[done] Issues found, see output above",
|
|
418
419
|
"cli.doctor.all_ok": "[done] Environment is healthy",
|
|
420
|
+
"cli.doctor.status_ok": "OK",
|
|
421
|
+
"cli.doctor.status_fail": "FAIL",
|
|
419
422
|
# ==================== types command ====================
|
|
420
423
|
"cli.types.description": "Generate type stub file to enable IDE completion",
|
|
421
424
|
"cli.types.output_help": "Output file path (default: ./_ep_types.py)",
|
|
@@ -205,6 +205,7 @@ TRANSLATIONS = {
|
|
|
205
205
|
"cli.list.count_adapters": "{count} 個のアダプター",
|
|
206
206
|
"cli.list.no_adapters": "該当するアダプターはありません",
|
|
207
207
|
"cli.list.no_packages": "{pkg_type} はありません",
|
|
208
|
+
"cli.list.empty_hint": "'epsdk install' でコンポーネントを閲覧・インストールするか、'epsdk init' でプロジェクトを作成できます",
|
|
208
209
|
# ==================== list-remote コマンド ====================
|
|
209
210
|
"cli.list_remote.description": "リモートで利用可能なコンポーネントを一覧表示",
|
|
210
211
|
"cli.list_remote.type_help": "一覧タイプ (デフォルト: all)",
|
|
@@ -416,6 +417,8 @@ TRANSLATIONS = {
|
|
|
416
417
|
"cli.doctor.proxy_none": "検出されません",
|
|
417
418
|
"cli.doctor.failed": "[完了] 対応が必要な問題があります。上記を確認してください",
|
|
418
419
|
"cli.doctor.all_ok": "[完了] 環境は正常です",
|
|
420
|
+
"cli.doctor.status_ok": "OK",
|
|
421
|
+
"cli.doctor.status_fail": "NG",
|
|
419
422
|
# ==================== types コマンド ====================
|
|
420
423
|
"cli.types.description": "型スタブファイルを生成して IDE 補完を有効化",
|
|
421
424
|
"cli.types.output_help": "出力ファイルパス(デフォルト: ./_ep_types.py)",
|
|
@@ -205,6 +205,7 @@ TRANSLATIONS = {
|
|
|
205
205
|
"cli.list.count_adapters": "{count} адаптера(ов)",
|
|
206
206
|
"cli.list.no_adapters": "Нет подходящих адаптеров",
|
|
207
207
|
"cli.list.no_packages": "Нет {pkg_type}",
|
|
208
|
+
"cli.list.empty_hint": "Выполните 'epsdk install' для просмотра и установки компонентов, или 'epsdk init' для создания проекта",
|
|
208
209
|
# ==================== команда list-remote ====================
|
|
209
210
|
"cli.list_remote.description": "Список удаленно доступных компонентов",
|
|
210
211
|
"cli.list_remote.type_help": "Тип списка (по умолчанию: all)",
|
|
@@ -416,6 +417,8 @@ TRANSLATIONS = {
|
|
|
416
417
|
"cli.doctor.proxy_none": "не обнаружен",
|
|
417
418
|
"cli.doctor.failed": "[готово] Есть проблемы, см. вывод выше",
|
|
418
419
|
"cli.doctor.all_ok": "[готово] Окружение в порядке",
|
|
420
|
+
"cli.doctor.status_ok": "OK",
|
|
421
|
+
"cli.doctor.status_fail": "FAIL",
|
|
419
422
|
# ==================== команда types ====================
|
|
420
423
|
"cli.types.description": "Сгенерировать файл заглушек типов для автодополнения IDE",
|
|
421
424
|
"cli.types.output_help": "Путь вывода (по умолчанию: ./_ep_types.py)",
|
|
@@ -205,6 +205,7 @@ TRANSLATIONS = {
|
|
|
205
205
|
"cli.list.count_adapters": "{count} 个适配器",
|
|
206
206
|
"cli.list.no_adapters": "没有符合条件的适配器",
|
|
207
207
|
"cli.list.no_packages": "没有{pkg_type}",
|
|
208
|
+
"cli.list.empty_hint": "可运行 'epsdk install' 浏览并安装组件,或运行 'epsdk init' 创建项目",
|
|
208
209
|
# ==================== list-remote 命令 ====================
|
|
209
210
|
"cli.list_remote.description": "列出远程可用的组件",
|
|
210
211
|
"cli.list_remote.type_help": "列出类型 (默认: all)",
|
|
@@ -416,6 +417,8 @@ TRANSLATIONS = {
|
|
|
416
417
|
"cli.doctor.proxy_none": "未检测到",
|
|
417
418
|
"cli.doctor.failed": "[诊断完成] 存在需要处理的问题,请参考上方输出",
|
|
418
419
|
"cli.doctor.all_ok": "[诊断完成] 环境正常",
|
|
420
|
+
"cli.doctor.status_ok": "正常",
|
|
421
|
+
"cli.doctor.status_fail": "异常",
|
|
419
422
|
# ==================== types 命令 ====================
|
|
420
423
|
"cli.types.description": "生成类型存根文件,启用 IDE 补全",
|
|
421
424
|
"cli.types.output_help": "输出文件路径(默认: ./_ep_types.py)",
|
|
@@ -205,6 +205,7 @@ TRANSLATIONS = {
|
|
|
205
205
|
"cli.list.count_adapters": "{count} 個適配器",
|
|
206
206
|
"cli.list.no_adapters": "沒有符合條件的適配器",
|
|
207
207
|
"cli.list.no_packages": "沒有{pkg_type}",
|
|
208
|
+
"cli.list.empty_hint": "可執行 'epsdk install' 瀏覽並安裝元件,或執行 'epsdk init' 建立專案",
|
|
208
209
|
# ==================== list-remote 命令 ====================
|
|
209
210
|
"cli.list_remote.description": "列出遠端可用的元件",
|
|
210
211
|
"cli.list_remote.type_help": "列出型別 (預設: all)",
|
|
@@ -416,6 +417,8 @@ TRANSLATIONS = {
|
|
|
416
417
|
"cli.doctor.proxy_none": "未偵測到",
|
|
417
418
|
"cli.doctor.failed": "[診斷完成] 存在需要處理的問題,請參考上方輸出",
|
|
418
419
|
"cli.doctor.all_ok": "[診斷完成] 環境正常",
|
|
420
|
+
"cli.doctor.status_ok": "正常",
|
|
421
|
+
"cli.doctor.status_fail": "異常",
|
|
419
422
|
# ==================== types 命令 ====================
|
|
420
423
|
"cli.types.description": "生成類型存根檔案,啟用 IDE 補全",
|
|
421
424
|
"cli.types.output_help": "輸出檔案路徑(預設: ./_ep_types.py)",
|
|
@@ -9,6 +9,7 @@ from collections.abc import Callable
|
|
|
9
9
|
from typing import Any
|
|
10
10
|
|
|
11
11
|
from rich.box import SIMPLE
|
|
12
|
+
from rich.markup import escape
|
|
12
13
|
from rich.prompt import Prompt
|
|
13
14
|
from rich.table import Table
|
|
14
15
|
from rich.text import Text
|
|
@@ -45,7 +46,9 @@ def _input(prompt_label: str = ">") -> str:
|
|
|
45
46
|
:param prompt_label: [str] 提示标签 (默认: ">")
|
|
46
47
|
:return: [str] 用户输入内容(已去除首尾空白)
|
|
47
48
|
"""
|
|
48
|
-
|
|
49
|
+
# 转义富文本标记
|
|
50
|
+
escaped = escape(prompt_label)
|
|
51
|
+
console.print(f" [dim]{escaped}[/] ", end="")
|
|
49
52
|
try:
|
|
50
53
|
return input().strip()
|
|
51
54
|
except (EOFError, KeyboardInterrupt):
|
|
@@ -59,7 +59,15 @@ async def _invoke_handler(handler_info: dict, event: Event) -> None:
|
|
|
59
59
|
else:
|
|
60
60
|
handler(event)
|
|
61
61
|
except Exception as e:
|
|
62
|
-
logger.error(
|
|
62
|
+
logger.error(
|
|
63
|
+
i18n.t(
|
|
64
|
+
"core.event.handler_error",
|
|
65
|
+
handler=_hname,
|
|
66
|
+
type=event.get("type", "") if isinstance(event, dict) else "",
|
|
67
|
+
owner=_owner or "<unknown>",
|
|
68
|
+
error=e,
|
|
69
|
+
)
|
|
70
|
+
)
|
|
63
71
|
return
|
|
64
72
|
finally:
|
|
65
73
|
_elapsed = _time.monotonic() - _t
|
|
@@ -1052,7 +1052,9 @@ class AdapterManager(ManagerBase):
|
|
|
1052
1052
|
logger.error(i18n.t("core.adapter.platform_not_exist", platform=platform))
|
|
1053
1053
|
return False
|
|
1054
1054
|
|
|
1055
|
-
config.setConfig(
|
|
1055
|
+
config.setConfig(
|
|
1056
|
+
CONFIG_KEY_ADAPTER_STATUS_OF.format(platform), True, immediate=True
|
|
1057
|
+
)
|
|
1056
1058
|
logger.info(i18n.t("core.adapter.platform_enabled", platform=platform))
|
|
1057
1059
|
return True
|
|
1058
1060
|
|
|
@@ -1075,7 +1077,9 @@ class AdapterManager(ManagerBase):
|
|
|
1075
1077
|
logger.error(i18n.t("core.adapter.platform_not_exist", platform=platform))
|
|
1076
1078
|
return False
|
|
1077
1079
|
|
|
1078
|
-
config.setConfig(
|
|
1080
|
+
config.setConfig(
|
|
1081
|
+
CONFIG_KEY_ADAPTER_STATUS_OF.format(platform), False, immediate=True
|
|
1082
|
+
)
|
|
1079
1083
|
logger.info(i18n.t("core.adapter.platform_disabled", platform=platform))
|
|
1080
1084
|
return True
|
|
1081
1085
|
|
|
@@ -1514,18 +1518,28 @@ class AdapterManager(ManagerBase):
|
|
|
1514
1518
|
# 调用过 wait_reply:纯等待属于交互白名单
|
|
1515
1519
|
if _pure > HANDLER_SLOW_THRESHOLD_SECS:
|
|
1516
1520
|
logger.warning(
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1521
|
+
i18n.t(
|
|
1522
|
+
"core.adapter.handler_slow",
|
|
1523
|
+
handler=_func_name,
|
|
1524
|
+
elapsed=f"{elapsed:.2f}",
|
|
1525
|
+
threshold=HANDLER_SLOW_THRESHOLD_SECS,
|
|
1526
|
+
type=event_type,
|
|
1527
|
+
platform=platform,
|
|
1528
|
+
tag=_owner_tag,
|
|
1529
|
+
)
|
|
1522
1530
|
)
|
|
1523
1531
|
else:
|
|
1524
1532
|
logger.trace(
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1533
|
+
i18n.t(
|
|
1534
|
+
"core.adapter.handler_slow_trace",
|
|
1535
|
+
handler=_func_name,
|
|
1536
|
+
elapsed=f"{elapsed:.2f}",
|
|
1537
|
+
wait=f"{_wait_total:.2f}",
|
|
1538
|
+
pure=f"{_pure:.2f}",
|
|
1539
|
+
type=event_type,
|
|
1540
|
+
platform=platform,
|
|
1541
|
+
tag=_owner_tag,
|
|
1542
|
+
)
|
|
1529
1543
|
)
|
|
1530
1544
|
elif elapsed > HANDLER_SLOW_THRESHOLD_SECS:
|
|
1531
1545
|
logger.warning(
|
|
@@ -248,6 +248,9 @@ class ConfigManager:
|
|
|
248
248
|
else:
|
|
249
249
|
self._cache = config
|
|
250
250
|
self._cache_timestamp = time.time()
|
|
251
|
+
# 外部修改重载后,丢弃与新文件一致的待写键,
|
|
252
|
+
# 避免陈旧的整棵/叶子脏键在下次 flush 时覆盖用户热更新
|
|
253
|
+
self._drop_redundant_dirty_keys()
|
|
251
254
|
if not self._cache:
|
|
252
255
|
self._log_config_error(
|
|
253
256
|
i18n.t("core.config.loaded_empty", path=self.CONFIG_FILE),
|
|
@@ -255,6 +258,32 @@ class ConfigManager:
|
|
|
255
258
|
)
|
|
256
259
|
return True
|
|
257
260
|
|
|
261
|
+
def _drop_redundant_dirty_keys(self) -> None:
|
|
262
|
+
"""
|
|
263
|
+
丢弃与新配置文件内容一致的待写键
|
|
264
|
+
|
|
265
|
+
配置重载(外部修改)后,部分待写键的值可能已与文件一致,
|
|
266
|
+
继续保留会在下次 flush 时用陈旧快照覆盖用户热更新。
|
|
267
|
+
仅当待写值已反映在缓存(即文件)中时才丢弃;真正未落盘的写入仍保留。
|
|
268
|
+
|
|
269
|
+
{!--< internal-use >!--}
|
|
270
|
+
{!--< /internal-use >!--}
|
|
271
|
+
"""
|
|
272
|
+
if not self._dirty_keys:
|
|
273
|
+
return
|
|
274
|
+
for key in list(self._dirty_keys):
|
|
275
|
+
value = self._dirty_keys[key]
|
|
276
|
+
current = self._cache
|
|
277
|
+
found = True
|
|
278
|
+
for k in key.split("."):
|
|
279
|
+
if isinstance(current, dict) and k in current:
|
|
280
|
+
current = current[k]
|
|
281
|
+
else:
|
|
282
|
+
found = False
|
|
283
|
+
break
|
|
284
|
+
if found and current == value:
|
|
285
|
+
del self._dirty_keys[key]
|
|
286
|
+
|
|
258
287
|
@staticmethod
|
|
259
288
|
def _log_config_error(message: str, level: str = "error") -> None:
|
|
260
289
|
"""
|
|
@@ -53,6 +53,12 @@ DEFAULT_SERVER_AUTO_START: Final[bool] = True
|
|
|
53
53
|
# 修改影响: Ctrl+C 后等待 uvicorn 关闭的耐心时间。超时后强制终止。
|
|
54
54
|
SERVER_SHUTDOWN_TIMEOUT_SECS: Final[float] = 5.0
|
|
55
55
|
|
|
56
|
+
# 路由服务器启动时端口被占用后的自动顺延尝试次数(含起始端口)。
|
|
57
|
+
# 运行时行为。启动时若端口被占用,自动依次尝试后续端口,
|
|
58
|
+
# 直至找到可用端口或达到该上限。实际监听端口通过 router.base_url 暴露。
|
|
59
|
+
# 修改影响: 设大允许更多顺延,设小更快放弃;设为 1 表示不顺延,占用即报错。
|
|
60
|
+
DEFAULT_SERVER_PORT_RETRY_LIMIT: Final[int] = 50
|
|
61
|
+
|
|
56
62
|
# ==============================================================================
|
|
57
63
|
# 配置键模板
|
|
58
64
|
#
|
|
@@ -766,6 +772,7 @@ __all__ = [
|
|
|
766
772
|
"DEFAULT_SERVER_AUTO_START",
|
|
767
773
|
"DEFAULT_SERVER_HOST",
|
|
768
774
|
"DEFAULT_SERVER_PORT",
|
|
775
|
+
"DEFAULT_SERVER_PORT_RETRY_LIMIT",
|
|
769
776
|
"DEFAULT_STRICT_MODE",
|
|
770
777
|
"DEFAULT_UNINIT_TIMEOUT_SECS",
|
|
771
778
|
"DEFAULT_USE_GLOBAL_DB",
|
|
@@ -33,6 +33,8 @@ TRANSLATIONS = {
|
|
|
33
33
|
"core.sdk.init.disabled_modules": "Disabled modules: {names}",
|
|
34
34
|
"core.sdk.init.strict_rejected": "Rejected by strict mode ({count}):",
|
|
35
35
|
"core.sdk.init.strict_rejected_reason": "({reason})",
|
|
36
|
+
"core.sdk.init.strict_tolerated": "Lenient mode: {count} component(s) have compliance issues but were loaded:",
|
|
37
|
+
"core.sdk.init.strict_action_hint": "To load skipped components, set ErisPulse.framework.strict_mode = 0, or add exemptions under ErisPulse.framework.strict_mode_exceptions.",
|
|
36
38
|
"core.sdk.init.success": "SDK initialized successfully (duration: {duration})",
|
|
37
39
|
"core.sdk.init.module_init_complete": "Module initialization complete",
|
|
38
40
|
"core.sdk.init.module_init_partial_failed": "Module initialization partially failed",
|
|
@@ -164,6 +166,7 @@ TRANSLATIONS = {
|
|
|
164
166
|
"core.adapter.bot_online": "Bot {platform}/{bot_id} online",
|
|
165
167
|
"core.adapter.handler_error": "Event handler execution error [{handler}] type={type} platform={platform}: {error}",
|
|
166
168
|
"core.adapter.handler_slow": "Event handler execution slow [{handler}] elapsed {elapsed}s > {threshold}s type={type} platform={platform}{tag}",
|
|
169
|
+
"core.adapter.handler_slow_trace": "Event handler [{handler}] took {elapsed}s (wait_reply={wait}s, pure={pure}s) interactive-wait, suppressed slow-warning type={type} platform={platform}{tag}",
|
|
167
170
|
"core.adapter.handler_drain_timeout": "{count} pending event handler(s) did not exit within {timeout}s, force cancelled",
|
|
168
171
|
"core.adapter.lifecycle_hooks_cleaned": "Adapter {platform} cleaned {count} lifecycle hook(s)",
|
|
169
172
|
"core.adapter.auto_discover_bot": "Auto-discovered Bot: {platform}/{bot_id}",
|
|
@@ -253,6 +256,9 @@ TRANSLATIONS = {
|
|
|
253
256
|
"core.router.started": "Router server started",
|
|
254
257
|
"core.router.start_failed_msg": "Router server startup failed",
|
|
255
258
|
"core.router.start_failed": "Failed to start server: {error}",
|
|
259
|
+
"core.router.port_in_use": "Port {host}:{port} is already in use; the router server could not start. Check whether another ErisPulse instance or another program is using this port (run `netstat -ano` to find the process holding it)",
|
|
260
|
+
"core.router.port_advance": "Port {host}:{requested} is already in use; automatically advanced to {host}:{port}",
|
|
261
|
+
"core.router.port_range_in_use": "Port {host}:{port} and the next {count} ports are all in use; the router server could not start. Check whether multiple ErisPulse instances or other programs are occupying these ports",
|
|
256
262
|
"core.router.stopping": "Stopping router server...",
|
|
257
263
|
"core.router.stopped_normal": "Router server stopped normally",
|
|
258
264
|
"core.router.stopped_cancelled": "Router server was cancelled",
|
|
@@ -303,7 +309,7 @@ TRANSLATIONS = {
|
|
|
303
309
|
"core.config.toml_malformed": "Configuration file {path} has a syntax error (line {line}, column {col}): {reason}",
|
|
304
310
|
"core.config.flush_malformed": "Configuration file {path} is corrupted (syntax error, line {line}, column {col}: {reason}); cannot merge-write. Please fix the config file and restart. Pending changes have been preserved.",
|
|
305
311
|
"core.config.permission_denied": "Permission denied when reading configuration file {path} (file may lack read access)",
|
|
306
|
-
"core.config.using_defaults_warning": "
|
|
312
|
+
"core.config.using_defaults_warning": "Failed to load the configuration file. Continuing with the last valid configuration; your recent edits were NOT applied. Fix the issue, then reload or restart.",
|
|
307
313
|
"core.config.loaded_empty": "Configuration file {path} was loaded but is empty",
|
|
308
314
|
"core.config.watcher_error": "Config watcher task error: {error}",
|
|
309
315
|
"core.config.restart_required": "Configuration '{key}' changed; a process restart is required to take effect",
|
|
@@ -327,6 +333,7 @@ TRANSLATIONS = {
|
|
|
327
333
|
# ==================== Loader ====================
|
|
328
334
|
"loader.adapter.discovered": "Discovered {count} adapters",
|
|
329
335
|
"loader.adapter.none": "No adapters found",
|
|
336
|
+
"loader.adapter.discovery_failed": "Adapter discovery failed, environment/dependency issue may be the cause: {error}",
|
|
330
337
|
"loader.adapter.load_failed": "Failed to load {group} entry-points: {error}",
|
|
331
338
|
"loader.adapter.systemexit": "SystemExit({code}) triggered while loading {group}, process exit blocked. Do not use sys.exit() or raise SystemExit",
|
|
332
339
|
"loader.adapter.load_single_failed": "Failed to load adapter {name}, skipped: {error}",
|
|
@@ -340,6 +347,7 @@ TRANSLATIONS = {
|
|
|
340
347
|
"loader.adapter.register_skipped": "Adapter {name} registration failed, skipped",
|
|
341
348
|
"loader.module.discovered": "Discovered {count} modules",
|
|
342
349
|
"loader.module.none": "No modules found",
|
|
350
|
+
"loader.module.discovery_failed": "Module discovery failed, environment/dependency issue may be the cause: {error}",
|
|
343
351
|
"loader.module.load_failed": "Failed to load {group} entry-points: {error}",
|
|
344
352
|
"loader.module.load_single_failed": "Failed to load module {name} from entry-point, skipped: {error}",
|
|
345
353
|
"loader.module.diag_hint": " → Hint: raise the log level to DEBUG for the full traceback; check the implementation of module {name}",
|
|
@@ -359,8 +367,30 @@ TRANSLATIONS = {
|
|
|
359
367
|
"loader.module.mount_lazy": "Mounting lazy-load module to sdk: {name}",
|
|
360
368
|
"loader.module.mount_eager": "Mounting eager-load module to sdk: {name}",
|
|
361
369
|
"loader.module.init_lazy_start": "Initializing lazy-load module {name}...",
|
|
370
|
+
"loader.module.systemexit_group": "SystemExit({code}) triggered while loading {group}, process exit blocked. Do not use sys.exit() or raise SystemExit",
|
|
371
|
+
"loader.module.systemexit_single": "Module {name} attempted to exit process (SystemExit({code})), skipped. Do not use sys.exit() or raise SystemExit",
|
|
372
|
+
"loader.module.strategy_failed": "Failed to call {method}() on module {name}: {error}",
|
|
373
|
+
"loader.module.lazy_init_failed": "Lazy-load module {name} initialization failed: {error}",
|
|
374
|
+
"loader.module.sync_init_failed": "Lazy-load module {name} synchronous initialization failed: {error}",
|
|
375
|
+
"loader.module.background_init_failed": "Lazy-load module {name} background initialization failed: {error}",
|
|
376
|
+
"loader.module.async_init_hint": "Module {name} requires async initialization, please call it in an async context",
|
|
377
|
+
"loader.module.lazy_init_done": "Lazy-load module {name} initialization complete",
|
|
378
|
+
"loader.module.sync_init_start": "Synchronously initializing lazy-load module {name}...",
|
|
379
|
+
"loader.module.sync_init_done": "Lazy-load module {name} synchronous initialization complete",
|
|
380
|
+
"loader.module.needs_async_load": "Module {name} requires async initialization, use 'await sdk.load_module(\"{name}\")' to initialize it",
|
|
381
|
+
"loader.module.init_failed_attr_get": "Module {name} initialization failed, cannot access attribute '{attr}'",
|
|
382
|
+
"loader.module.init_failed_attr_set": "Module {name} initialization failed, cannot set attribute '{attr}'",
|
|
383
|
+
# ==================== Base Loader ====================
|
|
384
|
+
"loader.base.load_start": "Loading {group} entry-points...",
|
|
385
|
+
"loader.base.load_done": "{group} loaded",
|
|
386
|
+
"loader.base.load_failed": "Failed to load {group} entry-points: {error}",
|
|
387
|
+
"loader.base.import_failed": "Failed to import {group}: {error}",
|
|
388
|
+
"loader.base.registered": "{prefix} {name} registered and {status}",
|
|
389
|
+
"loader.base.status_enabled": "enabled",
|
|
390
|
+
"loader.base.status_disabled": "disabled",
|
|
362
391
|
# ==================== Strict Mode ====================
|
|
363
392
|
"loader.strict.config_failed": "Failed to read strict_mode config, using default: {error}",
|
|
393
|
+
"loader.strict.invalid_level": "Invalid value '{value}' for ErisPulse.framework.strict_mode. Valid values are 0 (lenient), 1 (skip), 2 (fatal). Using default level ({level}).",
|
|
364
394
|
"loader.strict.exempted": "{type} '{name}' is exempted from strict mode ({reason}), continuing to load",
|
|
365
395
|
"loader.strict.tolerated": "Lenient mode: {type} '{name}' {reason}, attempting to load",
|
|
366
396
|
"loader.strict.rejected": "Strict mode: skipped {type} '{name}' ({reason}). To load it anyway, add exemption in ErisPulse.framework.strict_mode_exceptions.{list_key}, or set ErisPulse.framework.strict_mode = 0",
|
|
@@ -368,6 +398,13 @@ TRANSLATIONS = {
|
|
|
368
398
|
"loader.strict.fatal_report_header": "Strict mode (fatal) detected {count} violation(s), aborting startup:",
|
|
369
399
|
"loader.strict.fatal_report_item": " [{index}] {type} '{name}': {reason} {detail}",
|
|
370
400
|
"loader.strict.fatal_abort": "Strict mode (fatal): {count} violation(s) collected, startup aborted",
|
|
401
|
+
# ==================== Finder ====================
|
|
402
|
+
"finder.remote_load_unavailable": "_RemoteEntryPoint.load() is unavailable: cross-environment queries cannot load target-environment entry-point objects in the current process. Resolve via .value or call within the target environment.",
|
|
403
|
+
"finder.query_started": "Looking up {group} entry-points...",
|
|
404
|
+
"finder.found_count": "Found {count} {group} entry-points",
|
|
405
|
+
"finder.entry_points_query_failed": "Failed to find {group} entry-points: {error}",
|
|
406
|
+
"finder.remote_query_failed": "Failed to query {group} entry-points in target environment {python}: {stderr}",
|
|
407
|
+
"finder.remote_query_exception": "Failed to query entry-points in target environment {python}: {error}",
|
|
371
408
|
# ==================== Storage Router Display ====================
|
|
372
409
|
"core.router.lan_ipv4": "LAN IPv4",
|
|
373
410
|
"core.router.lan_ipv6": "LAN IPv6",
|
|
@@ -377,13 +414,14 @@ TRANSLATIONS = {
|
|
|
377
414
|
"core.logger.saved": "Logs have been saved to: {path}.",
|
|
378
415
|
"core.logger.save_failed": "Failed to save logs to {path}: {error}.",
|
|
379
416
|
"core.logger.invalid_level": "Invalid log level: {level}",
|
|
417
|
+
"core.logger.invalid_format": "Invalid log format: {fmt}. Valid values are rich, plain, json.",
|
|
380
418
|
"core.logger.module_level_set": "Module {module} log level set to {level}",
|
|
381
419
|
"core.logger.set_output_failed": "Failed to set log file {path}: {error}",
|
|
382
420
|
"core.logger.no_output_set": "Failed to set any log file.",
|
|
383
421
|
"core.logger.memory_limit_invalid": "Log memory limit must be greater than 0.",
|
|
384
422
|
"core.logger.attr.did_you_mean": "Logger module name '{input}' is very similar to registered '{suggestion}', possibly a typo",
|
|
385
423
|
# ==================== Event System ====================
|
|
386
|
-
"core.event.handler_error": "Event handler execution error: {error}",
|
|
424
|
+
"core.event.handler_error": "Event handler execution error [{handler}] type={type} owner={owner}: {error}",
|
|
387
425
|
"core.event.slow_handler_wait": "[EventHandler] Slow handler {handler} took {elapsed}s (wait_reply={wait}s, pure={pure}s, waits=[{waits}]){owner}",
|
|
388
426
|
"core.event.trace_handler_wait": "[EventHandler] {handler} took {elapsed}s (wait_reply={wait}s, pure={pure}s) interactive-wait, suppressed slow-warning{owner}",
|
|
389
427
|
"core.event.slow_handler": "[EventHandler] Slow handler {handler} took {elapsed}s{owner}",
|