AstrBot 4.10.0a2__py3-none-any.whl → 4.10.1__py3-none-any.whl
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.
- astrbot/cli/__init__.py +1 -1
- astrbot/core/config/default.py +1 -1
- astrbot/core/platform/sources/aiocqhttp/aiocqhttp_platform_adapter.py +17 -2
- astrbot/core/provider/sources/gemini_source.py +19 -3
- astrbot/core/star/command_management.py +12 -6
- astrbot/core/star/star_manager.py +5 -1
- astrbot/dashboard/routes/config.py +20 -8
- {astrbot-4.10.0a2.dist-info → astrbot-4.10.1.dist-info}/METADATA +1 -1
- {astrbot-4.10.0a2.dist-info → astrbot-4.10.1.dist-info}/RECORD +12 -12
- {astrbot-4.10.0a2.dist-info → astrbot-4.10.1.dist-info}/WHEEL +0 -0
- {astrbot-4.10.0a2.dist-info → astrbot-4.10.1.dist-info}/entry_points.txt +0 -0
- {astrbot-4.10.0a2.dist-info → astrbot-4.10.1.dist-info}/licenses/LICENSE +0 -0
astrbot/cli/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "4.10.
|
|
1
|
+
__version__ = "4.10.1"
|
astrbot/core/config/default.py
CHANGED
|
@@ -385,10 +385,25 @@ class AiocqhttpAdapter(Platform):
|
|
|
385
385
|
logger.error(f"获取 @ 用户信息失败: {e},此消息段将被忽略。")
|
|
386
386
|
|
|
387
387
|
message_str += "".join(at_parts)
|
|
388
|
+
elif t == "markdown":
|
|
389
|
+
text = m["data"].get("markdown") or m["data"].get("content", "")
|
|
390
|
+
abm.message.append(Plain(text=text))
|
|
391
|
+
message_str += text
|
|
388
392
|
else:
|
|
389
393
|
for m in m_group:
|
|
390
|
-
|
|
391
|
-
|
|
394
|
+
try:
|
|
395
|
+
if t not in ComponentTypes:
|
|
396
|
+
logger.warning(
|
|
397
|
+
f"不支持的消息段类型,已忽略: {t}, data={m['data']}"
|
|
398
|
+
)
|
|
399
|
+
continue
|
|
400
|
+
a = ComponentTypes[t](**m["data"])
|
|
401
|
+
abm.message.append(a)
|
|
402
|
+
except Exception as e:
|
|
403
|
+
logger.exception(
|
|
404
|
+
f"消息段解析失败: type={t}, data={m['data']}. {e}"
|
|
405
|
+
)
|
|
406
|
+
continue
|
|
392
407
|
|
|
393
408
|
abm.timestamp = int(time.time())
|
|
394
409
|
abm.message_str = message_str
|
|
@@ -138,7 +138,7 @@ class ProviderGoogleGenAI(Provider):
|
|
|
138
138
|
modalities = ["TEXT"]
|
|
139
139
|
|
|
140
140
|
tool_list: list[types.Tool] | None = []
|
|
141
|
-
model_name = payloads.get("model", self.get_model())
|
|
141
|
+
model_name = cast(str, payloads.get("model", self.get_model()))
|
|
142
142
|
native_coderunner = self.provider_config.get("gm_native_coderunner", False)
|
|
143
143
|
native_search = self.provider_config.get("gm_native_search", False)
|
|
144
144
|
url_context = self.provider_config.get("gm_url_context", False)
|
|
@@ -199,7 +199,16 @@ class ProviderGoogleGenAI(Provider):
|
|
|
199
199
|
|
|
200
200
|
# oper thinking config
|
|
201
201
|
thinking_config = None
|
|
202
|
-
if model_name
|
|
202
|
+
if model_name in [
|
|
203
|
+
"gemini-2.5-pro",
|
|
204
|
+
"gemini-2.5-pro-preview",
|
|
205
|
+
"gemini-2.5-flash",
|
|
206
|
+
"gemini-2.5-flash-preview",
|
|
207
|
+
"gemini-2.5-flash-lite",
|
|
208
|
+
"gemini-2.5-flash-lite-preview",
|
|
209
|
+
"gemini-robotics-er-1.5-preview",
|
|
210
|
+
"gemini-live-2.5-flash-preview-native-audio-09-2025",
|
|
211
|
+
]:
|
|
203
212
|
# The thinkingBudget parameter, introduced with the Gemini 2.5 series
|
|
204
213
|
thinking_budget = self.provider_config.get("gm_thinking_config", {}).get(
|
|
205
214
|
"budget", 0
|
|
@@ -208,7 +217,14 @@ class ProviderGoogleGenAI(Provider):
|
|
|
208
217
|
thinking_config = types.ThinkingConfig(
|
|
209
218
|
thinking_budget=thinking_budget,
|
|
210
219
|
)
|
|
211
|
-
elif model_name
|
|
220
|
+
elif model_name in [
|
|
221
|
+
"gemini-3-pro",
|
|
222
|
+
"gemini-3-pro-preview",
|
|
223
|
+
"gemini-3-flash",
|
|
224
|
+
"gemini-3-flash-preview",
|
|
225
|
+
"gemini-3-flash-lite",
|
|
226
|
+
"gemini-3-flash-lite-preview",
|
|
227
|
+
]:
|
|
212
228
|
# The thinkingLevel parameter, recommended for Gemini 3 models and onwards
|
|
213
229
|
# Gemini 2.5 series models don't support thinkingLevel; use thinkingBudget instead.
|
|
214
230
|
thinking_level = self.provider_config.get("gm_thinking_config", {}).get(
|
|
@@ -4,7 +4,7 @@ from collections import defaultdict
|
|
|
4
4
|
from dataclasses import dataclass, field
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
7
|
-
from astrbot.core import db_helper
|
|
7
|
+
from astrbot.core import db_helper, logger
|
|
8
8
|
from astrbot.core.db.po import CommandConfig
|
|
9
9
|
from astrbot.core.star.filter.command import CommandFilter
|
|
10
10
|
from astrbot.core.star.filter.command_group import CommandGroupFilter
|
|
@@ -192,12 +192,18 @@ def _collect_descriptors(include_sub_commands: bool) -> list[CommandDescriptor]:
|
|
|
192
192
|
"""收集指令,按需包含子指令。"""
|
|
193
193
|
descriptors: list[CommandDescriptor] = []
|
|
194
194
|
for handler in star_handlers_registry:
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
195
|
+
try:
|
|
196
|
+
desc = _build_descriptor(handler)
|
|
197
|
+
if not desc:
|
|
198
|
+
continue
|
|
199
|
+
if not include_sub_commands and desc.is_sub_command:
|
|
200
|
+
continue
|
|
201
|
+
descriptors.append(desc)
|
|
202
|
+
except Exception as e:
|
|
203
|
+
logger.warning(
|
|
204
|
+
f"解析指令处理函数 {handler.handler_full_name} 失败,跳过该指令。原因: {e!s}"
|
|
205
|
+
)
|
|
199
206
|
continue
|
|
200
|
-
descriptors.append(desc)
|
|
201
207
|
return descriptors
|
|
202
208
|
|
|
203
209
|
|
|
@@ -631,7 +631,11 @@ class PluginManager:
|
|
|
631
631
|
# 清除 pip.main 导致的多余的 logging handlers
|
|
632
632
|
for handler in logging.root.handlers[:]:
|
|
633
633
|
logging.root.removeHandler(handler)
|
|
634
|
-
|
|
634
|
+
try:
|
|
635
|
+
await sync_command_configs()
|
|
636
|
+
except Exception as e:
|
|
637
|
+
logger.error(f"同步指令配置失败: {e!s}")
|
|
638
|
+
logger.error(traceback.format_exc())
|
|
635
639
|
|
|
636
640
|
if not fail_rec:
|
|
637
641
|
return True, None
|
|
@@ -185,23 +185,30 @@ class ConfigRoute(Route):
|
|
|
185
185
|
"/config/provider/list": ("GET", self.get_provider_config_list),
|
|
186
186
|
"/config/provider/model_list": ("GET", self.get_provider_model_list),
|
|
187
187
|
"/config/provider/get_embedding_dim": ("POST", self.get_embedding_dim),
|
|
188
|
-
"/config/provider_sources
|
|
188
|
+
"/config/provider_sources/models": (
|
|
189
189
|
"GET",
|
|
190
190
|
self.get_provider_source_models,
|
|
191
191
|
),
|
|
192
|
-
"/config/provider_sources
|
|
192
|
+
"/config/provider_sources/update": (
|
|
193
193
|
"POST",
|
|
194
194
|
self.update_provider_source,
|
|
195
195
|
),
|
|
196
|
-
"/config/provider_sources
|
|
196
|
+
"/config/provider_sources/delete": (
|
|
197
197
|
"POST",
|
|
198
198
|
self.delete_provider_source,
|
|
199
199
|
),
|
|
200
200
|
}
|
|
201
201
|
self.register_routes()
|
|
202
202
|
|
|
203
|
-
async def delete_provider_source(self
|
|
203
|
+
async def delete_provider_source(self):
|
|
204
204
|
"""删除 provider_source,并更新关联的 providers"""
|
|
205
|
+
post_data = await request.json
|
|
206
|
+
if not post_data:
|
|
207
|
+
return Response().error("缺少配置数据").__dict__
|
|
208
|
+
|
|
209
|
+
provider_source_id = post_data.get("id")
|
|
210
|
+
if not provider_source_id:
|
|
211
|
+
return Response().error("缺少 provider_source_id").__dict__
|
|
205
212
|
|
|
206
213
|
provider_sources = self.config.get("provider_sources", [])
|
|
207
214
|
target_idx = next(
|
|
@@ -235,15 +242,16 @@ class ConfigRoute(Route):
|
|
|
235
242
|
|
|
236
243
|
return Response().ok(message="删除 provider source 成功").__dict__
|
|
237
244
|
|
|
238
|
-
async def update_provider_source(self
|
|
245
|
+
async def update_provider_source(self):
|
|
239
246
|
"""更新或新增 provider_source,并重载关联的 providers"""
|
|
240
|
-
|
|
241
247
|
post_data = await request.json
|
|
242
248
|
if not post_data:
|
|
243
249
|
return Response().error("缺少配置数据").__dict__
|
|
244
250
|
|
|
245
251
|
new_source_config = post_data.get("config") or post_data
|
|
246
|
-
original_id =
|
|
252
|
+
original_id = post_data.get("original_id")
|
|
253
|
+
if not original_id:
|
|
254
|
+
return Response().error("缺少 original_id").__dict__
|
|
247
255
|
|
|
248
256
|
if not isinstance(new_source_config, dict):
|
|
249
257
|
return Response().error("缺少或错误的配置数据").__dict__
|
|
@@ -684,11 +692,15 @@ class ConfigRoute(Route):
|
|
|
684
692
|
logger.error(traceback.format_exc())
|
|
685
693
|
return Response().error(f"获取嵌入维度失败: {e!s}").__dict__
|
|
686
694
|
|
|
687
|
-
async def get_provider_source_models(self
|
|
695
|
+
async def get_provider_source_models(self):
|
|
688
696
|
"""获取指定 provider_source 支持的模型列表
|
|
689
697
|
|
|
690
698
|
本质上会临时初始化一个 Provider 实例,调用 get_models() 获取模型列表,然后销毁实例
|
|
691
699
|
"""
|
|
700
|
+
provider_source_id = request.args.get("source_id")
|
|
701
|
+
if not provider_source_id:
|
|
702
|
+
return Response().error("缺少参数 source_id").__dict__
|
|
703
|
+
|
|
692
704
|
try:
|
|
693
705
|
from astrbot.core.provider.register import provider_cls_map
|
|
694
706
|
|
|
@@ -8,7 +8,7 @@ astrbot/api/platform/__init__.py,sha256=HXvAy_KLtOJspoGVgDtLa7VjIZoF6WK3Puww55yy
|
|
|
8
8
|
astrbot/api/provider/__init__.py,sha256=mJVcon0snjn_xYirk2hntwba6ymIYYC-ZKKmxvx-jok,379
|
|
9
9
|
astrbot/api/star/__init__.py,sha256=OxgHGtWn3lEQGjb4twbpbWnRepUevPu7gxtDAkAsfhQ,250
|
|
10
10
|
astrbot/api/util/__init__.py,sha256=L1O_mFEUDk8V4lEPsT5iiNbIiOVh7HbrNmitqzUWMZg,180
|
|
11
|
-
astrbot/cli/__init__.py,sha256=
|
|
11
|
+
astrbot/cli/__init__.py,sha256=ogZ1wJ10Itlh9CdbwovCzGjxyYPJlQvG3lxFz6oBJ-c,23
|
|
12
12
|
astrbot/cli/__main__.py,sha256=QobgMyFoLNTgI_OYddhGOZ9ZvQeBVjjz79mA2cC2OEU,1758
|
|
13
13
|
astrbot/cli/commands/__init__.py,sha256=eAgppZQIqFO1ylQJFABeYrzQ0oZqPWjtE80aKIPB3ks,149
|
|
14
14
|
astrbot/cli/commands/cmd_conf.py,sha256=6-YLicBt_zjWTzaVLUJ1VQLQPbDEPYACB9IVnN8Zvng,6330
|
|
@@ -56,7 +56,7 @@ astrbot/core/agent/runners/dify/dify_agent_runner.py,sha256=LYwpjOcBWf3XlwNVzrDv
|
|
|
56
56
|
astrbot/core/agent/runners/dify/dify_api_client.py,sha256=OXukDVgNx3VmYw6OCzjXyP8JmDWEFuy81sD9XnC4VRo,6530
|
|
57
57
|
astrbot/core/config/__init__.py,sha256=vZjtpC7vr-IvBgSUtbS04C0wpulmCG5tPmcEP1WYE_4,172
|
|
58
58
|
astrbot/core/config/astrbot_config.py,sha256=6bUTnMCOyaS8s6ELsWctDfUFTB53fKJQNu272dZXkdU,6347
|
|
59
|
-
astrbot/core/config/default.py,sha256=
|
|
59
|
+
astrbot/core/config/default.py,sha256=sGTmORVNNVAqbXoNyOnBCGSE3Cs6sYpE0UdFrRxvBRc,147674
|
|
60
60
|
astrbot/core/config/i18n_utils.py,sha256=HJn_0XeeVS9ryCBelYfnc0nEn10LlX702fcSSFrF1J8,3879
|
|
61
61
|
astrbot/core/db/__init__.py,sha256=OnvNaC76hYp28Bq9zkFXMl19zn7w-FC1zxyLgsemGvU,13400
|
|
62
62
|
astrbot/core/db/po.py,sha256=eoI4sjpFb9CwRy6_Gf6-zHVSka6-oJr0LA4qcepqHzU,11804
|
|
@@ -129,7 +129,7 @@ astrbot/core/platform/platform.py,sha256=U2jq248bfPaAcIa8PUO5aiPyAOGIN1lz6LVnqQO
|
|
|
129
129
|
astrbot/core/platform/platform_metadata.py,sha256=PCqNk-H-V7BtiQXbbyHd84s43BBIZNhUQ9X-SVKP3uM,693
|
|
130
130
|
astrbot/core/platform/register.py,sha256=ptIPhVvbzODuWwXr8J0jJSzSPfv3rr7F67gXqvIpvvk,1985
|
|
131
131
|
astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py,sha256=ycNdNPKUnBJ3hJuDn_S8GM_W7XFbhumpotM8yqcOrqg,8146
|
|
132
|
-
astrbot/core/platform/sources/aiocqhttp/aiocqhttp_platform_adapter.py,sha256=
|
|
132
|
+
astrbot/core/platform/sources/aiocqhttp/aiocqhttp_platform_adapter.py,sha256=y6fx7UVkBAm67aTQO9dDQLpdcnfPt5kXco_sN_mL620,18642
|
|
133
133
|
astrbot/core/platform/sources/dingtalk/dingtalk_adapter.py,sha256=FBlNB7BpwGIp0frGNY45seep4hV06fPmckfOH7qFS58,9558
|
|
134
134
|
astrbot/core/platform/sources/dingtalk/dingtalk_event.py,sha256=01If6T-YJqlCfmyIh6UO668LA1f5EKUqeoZLVYkxds0,2850
|
|
135
135
|
astrbot/core/platform/sources/discord/client.py,sha256=YGrUSopQKDRFfzjCdcBQm-EcNWonBwAgXzW678G0e_c,5181
|
|
@@ -190,7 +190,7 @@ astrbot/core/provider/sources/dashscope_tts.py,sha256=-qBMwbIt_QSmWCT_uPAxrXSYuE
|
|
|
190
190
|
astrbot/core/provider/sources/edge_tts_source.py,sha256=dsf6YtSGzCJvas3BqBwHSn8vlMgQ_vgD9NEwngqDlEo,4690
|
|
191
191
|
astrbot/core/provider/sources/fishaudio_tts_api_source.py,sha256=z5yJuc47iky31N0Za3Li7uwMP15N1gsKJkV9ybIbKew,5556
|
|
192
192
|
astrbot/core/provider/sources/gemini_embedding_source.py,sha256=bj4iXnMyONTyUBmBFeezPcBpjtfX_UBjMrbwMFyCis8,2607
|
|
193
|
-
astrbot/core/provider/sources/gemini_source.py,sha256=
|
|
193
|
+
astrbot/core/provider/sources/gemini_source.py,sha256=o4vrlq6Pp7hcPJpVq4ppx1IOmG_1JPJNrwqt923QlMw,33916
|
|
194
194
|
astrbot/core/provider/sources/gemini_tts_source.py,sha256=6LJIT2aTjoZaMszjYRzDu38prsO9G5Xg7SzJmQb2TzE,2880
|
|
195
195
|
astrbot/core/provider/sources/groq_source.py,sha256=NqmiQn37mrMsaTyGX25eNzMpIgkCifY-5TJO8DFzHaA,456
|
|
196
196
|
astrbot/core/provider/sources/gsv_selfhosted_source.py,sha256=RYQgwCc67N7RWPaODN4sSLJZn6o5gpgk_jF_KaRnD0M,5942
|
|
@@ -209,14 +209,14 @@ astrbot/core/provider/sources/xinference_stt_provider.py,sha256=DPEc7cVo2KXKGIgb
|
|
|
209
209
|
astrbot/core/provider/sources/zhipu_source.py,sha256=oOCPXGsR9PLWOuu3h8RSVNRw1Qy2Se6dwmeFR3zk3GM,612
|
|
210
210
|
astrbot/core/star/README.md,sha256=LXxqxp3xv_oejO8ocBPOrbmLe0WB4feu43fYDNddHTQ,161
|
|
211
211
|
astrbot/core/star/__init__.py,sha256=iTlnjfEGJGy--78PhG7F1cKj9VwJVcDNFtGomX8hRO0,2229
|
|
212
|
-
astrbot/core/star/command_management.py,sha256=
|
|
212
|
+
astrbot/core/star/command_management.py,sha256=QJ-3jP9gA86iv-jBKAeuFkqYqJ3zkllHQXwjjKXmsao,16557
|
|
213
213
|
astrbot/core/star/config.py,sha256=FgrBz_fUrBU0-9BxD8enX-xGNGVbFxst3UT10sboYNA,3531
|
|
214
214
|
astrbot/core/star/context.py,sha256=zudyvlcVJb5zO7pAh_TGQOUQ3q8JSoKM1wldcciXypw,21234
|
|
215
215
|
astrbot/core/star/session_llm_manager.py,sha256=W_ZgNDyUPjMQGccqnK83hFjZvSCv5BLQeyv5fHvRLUw,5307
|
|
216
216
|
astrbot/core/star/session_plugin_manager.py,sha256=8sEzOxf_Gq-dwK_S-4rwocAFsYzx7Yi4FJuMRttPTac,2830
|
|
217
217
|
astrbot/core/star/star.py,sha256=Wkf81teNZ27JE_JrENuP0SrpFc2uFYRxHQsWo8R9-No,1826
|
|
218
218
|
astrbot/core/star/star_handler.py,sha256=x95UxHomijT6AamIlpij9Q2PweOw0jXPciFlS5IpPVI,7616
|
|
219
|
-
astrbot/core/star/star_manager.py,sha256=
|
|
219
|
+
astrbot/core/star/star_manager.py,sha256=GDN_aOJLLakQBN0wuEyD3hAtyNln_9UzX8JIryUupUA,41165
|
|
220
220
|
astrbot/core/star/star_tools.py,sha256=4q8emjyTbyIsVXHmzT88kX9uK28rIhlHc0re40Xm6m0,10847
|
|
221
221
|
astrbot/core/star/updator.py,sha256=4pl42Ks_yjJ3kydx3BwOqocAczhhFBrRnxhBKh4_0Eo,3106
|
|
222
222
|
astrbot/core/star/filter/__init__.py,sha256=bC6eHXh0CjzHmn-LTvsanWReoGIPhhMnBSrMLh97hZQ,470
|
|
@@ -260,7 +260,7 @@ astrbot/dashboard/routes/__init__.py,sha256=57ZYHYQfNI-YAiA8K9m2tRJcHzMKcZ02Vu-A
|
|
|
260
260
|
astrbot/dashboard/routes/auth.py,sha256=rYkvt3MpCY9BhWjG0DUoX3YaBkJT1Id7M2pKqTmXbvo,2946
|
|
261
261
|
astrbot/dashboard/routes/chat.py,sha256=ntQrgrnOTIep_9Ycb1DCZjZBJPtlIJUO2YnTvC1GXFQ,27120
|
|
262
262
|
astrbot/dashboard/routes/command.py,sha256=OLrDDUAE5zpxZMRJ3_IGe-6xFEpPwcXcd-EJ60e9OHI,2862
|
|
263
|
-
astrbot/dashboard/routes/config.py,sha256=
|
|
263
|
+
astrbot/dashboard/routes/config.py,sha256=4CsabE-ARxmLSGg30ZxlW-EvGHD-ppWHH03jml5-uQc,43326
|
|
264
264
|
astrbot/dashboard/routes/conversation.py,sha256=TWGY7BJ9QfmbxurAieBrbMmCi4_Ua2klxsAUlSRXbng,14302
|
|
265
265
|
astrbot/dashboard/routes/file.py,sha256=gULvXP9PnVOQlyv_PCEzZQE5ptnGQEjFPvwOLxdVgb4,708
|
|
266
266
|
astrbot/dashboard/routes/knowledge_base.py,sha256=GZ_iDYV2uXXzvGMF-4VJ8hZxLdHIWSSfg_3wlWwsizA,46081
|
|
@@ -275,8 +275,8 @@ astrbot/dashboard/routes/static_file.py,sha256=7KnNcOb1BVqSTft114LhGsDkfg69X2jHE
|
|
|
275
275
|
astrbot/dashboard/routes/t2i.py,sha256=F6smxdL99MF7cRw3hqS6-2GErw8Zhsv0V0mfBUeEk-c,8931
|
|
276
276
|
astrbot/dashboard/routes/tools.py,sha256=mMwVFw_VOlpqy_WZg1A-ddGtYa5L5QLWYawl37PT0-c,15354
|
|
277
277
|
astrbot/dashboard/routes/update.py,sha256=qXiqQ_dbqRVftOzGgCQrvK8-qopVK6zKhhVVJ9SK26U,6648
|
|
278
|
-
astrbot-4.10.
|
|
279
|
-
astrbot-4.10.
|
|
280
|
-
astrbot-4.10.
|
|
281
|
-
astrbot-4.10.
|
|
282
|
-
astrbot-4.10.
|
|
278
|
+
astrbot-4.10.1.dist-info/METADATA,sha256=lBZaSiFV--2ampd45pQJ3_Cz5PRwJWkXQHJbmD9Xerc,11925
|
|
279
|
+
astrbot-4.10.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
280
|
+
astrbot-4.10.1.dist-info/entry_points.txt,sha256=OEF09YmhBWYuViXrvTLLpstF4ccmNwDL8r7nnFD0pfI,53
|
|
281
|
+
astrbot-4.10.1.dist-info/licenses/LICENSE,sha256=zPfQj5Mq8-gThIiBcxETr7t8gND9bZWOjTGQAr80TQI,34500
|
|
282
|
+
astrbot-4.10.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|