AstrBot 3.5.6__py3-none-any.whl → 4.7.0__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/api/__init__.py +16 -4
- astrbot/api/all.py +2 -1
- astrbot/api/event/__init__.py +5 -6
- astrbot/api/event/filter/__init__.py +37 -34
- astrbot/api/platform/__init__.py +7 -8
- astrbot/api/provider/__init__.py +8 -7
- astrbot/api/star/__init__.py +3 -4
- astrbot/api/util/__init__.py +2 -2
- astrbot/cli/__init__.py +1 -0
- astrbot/cli/__main__.py +18 -197
- astrbot/cli/commands/__init__.py +6 -0
- astrbot/cli/commands/cmd_conf.py +209 -0
- astrbot/cli/commands/cmd_init.py +56 -0
- astrbot/cli/commands/cmd_plug.py +245 -0
- astrbot/cli/commands/cmd_run.py +62 -0
- astrbot/cli/utils/__init__.py +18 -0
- astrbot/cli/utils/basic.py +76 -0
- astrbot/cli/utils/plugin.py +246 -0
- astrbot/cli/utils/version_comparator.py +90 -0
- astrbot/core/__init__.py +17 -19
- astrbot/core/agent/agent.py +14 -0
- astrbot/core/agent/handoff.py +38 -0
- astrbot/core/agent/hooks.py +30 -0
- astrbot/core/agent/mcp_client.py +385 -0
- astrbot/core/agent/message.py +175 -0
- astrbot/core/agent/response.py +14 -0
- astrbot/core/agent/run_context.py +22 -0
- astrbot/core/agent/runners/__init__.py +3 -0
- astrbot/core/agent/runners/base.py +65 -0
- astrbot/core/agent/runners/coze/coze_agent_runner.py +367 -0
- astrbot/core/agent/runners/coze/coze_api_client.py +324 -0
- astrbot/core/agent/runners/dashscope/dashscope_agent_runner.py +403 -0
- astrbot/core/agent/runners/dify/dify_agent_runner.py +336 -0
- astrbot/core/agent/runners/dify/dify_api_client.py +195 -0
- astrbot/core/agent/runners/tool_loop_agent_runner.py +400 -0
- astrbot/core/agent/tool.py +285 -0
- astrbot/core/agent/tool_executor.py +17 -0
- astrbot/core/astr_agent_context.py +19 -0
- astrbot/core/astr_agent_hooks.py +36 -0
- astrbot/core/astr_agent_run_util.py +80 -0
- astrbot/core/astr_agent_tool_exec.py +246 -0
- astrbot/core/astrbot_config_mgr.py +275 -0
- astrbot/core/config/__init__.py +2 -2
- astrbot/core/config/astrbot_config.py +60 -20
- astrbot/core/config/default.py +1972 -453
- astrbot/core/config/i18n_utils.py +110 -0
- astrbot/core/conversation_mgr.py +285 -75
- astrbot/core/core_lifecycle.py +167 -62
- astrbot/core/db/__init__.py +305 -102
- astrbot/core/db/migration/helper.py +69 -0
- astrbot/core/db/migration/migra_3_to_4.py +357 -0
- astrbot/core/db/migration/migra_45_to_46.py +44 -0
- astrbot/core/db/migration/migra_webchat_session.py +131 -0
- astrbot/core/db/migration/shared_preferences_v3.py +48 -0
- astrbot/core/db/migration/sqlite_v3.py +497 -0
- astrbot/core/db/po.py +259 -55
- astrbot/core/db/sqlite.py +773 -528
- astrbot/core/db/vec_db/base.py +73 -0
- astrbot/core/db/vec_db/faiss_impl/__init__.py +3 -0
- astrbot/core/db/vec_db/faiss_impl/document_storage.py +392 -0
- astrbot/core/db/vec_db/faiss_impl/embedding_storage.py +93 -0
- astrbot/core/db/vec_db/faiss_impl/sqlite_init.sql +17 -0
- astrbot/core/db/vec_db/faiss_impl/vec_db.py +204 -0
- astrbot/core/event_bus.py +26 -22
- astrbot/core/exceptions.py +9 -0
- astrbot/core/file_token_service.py +98 -0
- astrbot/core/initial_loader.py +19 -10
- astrbot/core/knowledge_base/chunking/__init__.py +9 -0
- astrbot/core/knowledge_base/chunking/base.py +25 -0
- astrbot/core/knowledge_base/chunking/fixed_size.py +59 -0
- astrbot/core/knowledge_base/chunking/recursive.py +161 -0
- astrbot/core/knowledge_base/kb_db_sqlite.py +301 -0
- astrbot/core/knowledge_base/kb_helper.py +642 -0
- astrbot/core/knowledge_base/kb_mgr.py +330 -0
- astrbot/core/knowledge_base/models.py +120 -0
- astrbot/core/knowledge_base/parsers/__init__.py +13 -0
- astrbot/core/knowledge_base/parsers/base.py +51 -0
- astrbot/core/knowledge_base/parsers/markitdown_parser.py +26 -0
- astrbot/core/knowledge_base/parsers/pdf_parser.py +101 -0
- astrbot/core/knowledge_base/parsers/text_parser.py +42 -0
- astrbot/core/knowledge_base/parsers/url_parser.py +103 -0
- astrbot/core/knowledge_base/parsers/util.py +13 -0
- astrbot/core/knowledge_base/prompts.py +65 -0
- astrbot/core/knowledge_base/retrieval/__init__.py +14 -0
- astrbot/core/knowledge_base/retrieval/hit_stopwords.txt +767 -0
- astrbot/core/knowledge_base/retrieval/manager.py +276 -0
- astrbot/core/knowledge_base/retrieval/rank_fusion.py +142 -0
- astrbot/core/knowledge_base/retrieval/sparse_retriever.py +136 -0
- astrbot/core/log.py +21 -15
- astrbot/core/message/components.py +413 -287
- astrbot/core/message/message_event_result.py +35 -24
- astrbot/core/persona_mgr.py +192 -0
- astrbot/core/pipeline/__init__.py +14 -14
- astrbot/core/pipeline/content_safety_check/stage.py +13 -9
- astrbot/core/pipeline/content_safety_check/strategies/__init__.py +1 -2
- astrbot/core/pipeline/content_safety_check/strategies/baidu_aip.py +13 -14
- astrbot/core/pipeline/content_safety_check/strategies/keywords.py +2 -1
- astrbot/core/pipeline/content_safety_check/strategies/strategy.py +6 -6
- astrbot/core/pipeline/context.py +7 -1
- astrbot/core/pipeline/context_utils.py +107 -0
- astrbot/core/pipeline/preprocess_stage/stage.py +63 -36
- astrbot/core/pipeline/process_stage/method/agent_request.py +48 -0
- astrbot/core/pipeline/process_stage/method/agent_sub_stages/internal.py +464 -0
- astrbot/core/pipeline/process_stage/method/agent_sub_stages/third_party.py +202 -0
- astrbot/core/pipeline/process_stage/method/star_request.py +26 -32
- astrbot/core/pipeline/process_stage/stage.py +21 -15
- astrbot/core/pipeline/process_stage/utils.py +125 -0
- astrbot/core/pipeline/rate_limit_check/stage.py +34 -36
- astrbot/core/pipeline/respond/stage.py +142 -101
- astrbot/core/pipeline/result_decorate/stage.py +124 -57
- astrbot/core/pipeline/scheduler.py +21 -16
- astrbot/core/pipeline/session_status_check/stage.py +37 -0
- astrbot/core/pipeline/stage.py +11 -76
- astrbot/core/pipeline/waking_check/stage.py +69 -33
- astrbot/core/pipeline/whitelist_check/stage.py +10 -7
- astrbot/core/platform/__init__.py +6 -6
- astrbot/core/platform/astr_message_event.py +107 -129
- astrbot/core/platform/astrbot_message.py +32 -12
- astrbot/core/platform/manager.py +62 -18
- astrbot/core/platform/message_session.py +30 -0
- astrbot/core/platform/platform.py +16 -24
- astrbot/core/platform/platform_metadata.py +9 -4
- astrbot/core/platform/register.py +12 -7
- astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py +136 -60
- astrbot/core/platform/sources/aiocqhttp/aiocqhttp_platform_adapter.py +126 -46
- astrbot/core/platform/sources/dingtalk/dingtalk_adapter.py +63 -31
- astrbot/core/platform/sources/dingtalk/dingtalk_event.py +30 -26
- astrbot/core/platform/sources/discord/client.py +129 -0
- astrbot/core/platform/sources/discord/components.py +139 -0
- astrbot/core/platform/sources/discord/discord_platform_adapter.py +473 -0
- astrbot/core/platform/sources/discord/discord_platform_event.py +313 -0
- astrbot/core/platform/sources/lark/lark_adapter.py +27 -18
- astrbot/core/platform/sources/lark/lark_event.py +39 -13
- astrbot/core/platform/sources/misskey/misskey_adapter.py +770 -0
- astrbot/core/platform/sources/misskey/misskey_api.py +964 -0
- astrbot/core/platform/sources/misskey/misskey_event.py +163 -0
- astrbot/core/platform/sources/misskey/misskey_utils.py +550 -0
- astrbot/core/platform/sources/qqofficial/qqofficial_message_event.py +149 -33
- astrbot/core/platform/sources/qqofficial/qqofficial_platform_adapter.py +41 -26
- astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_adapter.py +36 -17
- astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_event.py +3 -1
- astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_server.py +14 -8
- astrbot/core/platform/sources/satori/satori_adapter.py +792 -0
- astrbot/core/platform/sources/satori/satori_event.py +432 -0
- astrbot/core/platform/sources/slack/client.py +164 -0
- astrbot/core/platform/sources/slack/slack_adapter.py +416 -0
- astrbot/core/platform/sources/slack/slack_event.py +253 -0
- astrbot/core/platform/sources/telegram/tg_adapter.py +100 -43
- astrbot/core/platform/sources/telegram/tg_event.py +136 -36
- astrbot/core/platform/sources/webchat/webchat_adapter.py +72 -22
- astrbot/core/platform/sources/webchat/webchat_event.py +46 -22
- astrbot/core/platform/sources/webchat/webchat_queue_mgr.py +35 -0
- astrbot/core/platform/sources/wechatpadpro/wechatpadpro_adapter.py +926 -0
- astrbot/core/platform/sources/wechatpadpro/wechatpadpro_message_event.py +178 -0
- astrbot/core/platform/sources/wechatpadpro/xml_data_parser.py +159 -0
- astrbot/core/platform/sources/wecom/wecom_adapter.py +169 -27
- astrbot/core/platform/sources/wecom/wecom_event.py +162 -77
- astrbot/core/platform/sources/wecom/wecom_kf.py +279 -0
- astrbot/core/platform/sources/wecom/wecom_kf_message.py +196 -0
- astrbot/core/platform/sources/wecom_ai_bot/WXBizJsonMsgCrypt.py +297 -0
- astrbot/core/platform/sources/wecom_ai_bot/__init__.py +15 -0
- astrbot/core/platform/sources/wecom_ai_bot/ierror.py +19 -0
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_adapter.py +472 -0
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_api.py +417 -0
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_event.py +152 -0
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_queue_mgr.py +153 -0
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_server.py +168 -0
- astrbot/core/platform/sources/wecom_ai_bot/wecomai_utils.py +209 -0
- astrbot/core/platform/sources/weixin_official_account/weixin_offacc_adapter.py +306 -0
- astrbot/core/platform/sources/weixin_official_account/weixin_offacc_event.py +186 -0
- astrbot/core/platform_message_history_mgr.py +49 -0
- astrbot/core/provider/__init__.py +2 -3
- astrbot/core/provider/entites.py +8 -8
- astrbot/core/provider/entities.py +154 -98
- astrbot/core/provider/func_tool_manager.py +446 -458
- astrbot/core/provider/manager.py +345 -207
- astrbot/core/provider/provider.py +188 -73
- astrbot/core/provider/register.py +9 -7
- astrbot/core/provider/sources/anthropic_source.py +295 -115
- astrbot/core/provider/sources/azure_tts_source.py +224 -0
- astrbot/core/provider/sources/bailian_rerank_source.py +236 -0
- astrbot/core/provider/sources/dashscope_tts.py +138 -14
- astrbot/core/provider/sources/edge_tts_source.py +24 -19
- astrbot/core/provider/sources/fishaudio_tts_api_source.py +58 -13
- astrbot/core/provider/sources/gemini_embedding_source.py +61 -0
- astrbot/core/provider/sources/gemini_source.py +310 -132
- astrbot/core/provider/sources/gemini_tts_source.py +81 -0
- astrbot/core/provider/sources/groq_source.py +15 -0
- astrbot/core/provider/sources/gsv_selfhosted_source.py +151 -0
- astrbot/core/provider/sources/gsvi_tts_source.py +14 -7
- astrbot/core/provider/sources/minimax_tts_api_source.py +159 -0
- astrbot/core/provider/sources/openai_embedding_source.py +40 -0
- astrbot/core/provider/sources/openai_source.py +241 -145
- astrbot/core/provider/sources/openai_tts_api_source.py +18 -7
- astrbot/core/provider/sources/sensevoice_selfhosted_source.py +13 -11
- astrbot/core/provider/sources/vllm_rerank_source.py +71 -0
- astrbot/core/provider/sources/volcengine_tts.py +115 -0
- astrbot/core/provider/sources/whisper_api_source.py +18 -13
- astrbot/core/provider/sources/whisper_selfhosted_source.py +19 -12
- astrbot/core/provider/sources/xinference_rerank_source.py +116 -0
- astrbot/core/provider/sources/xinference_stt_provider.py +197 -0
- astrbot/core/provider/sources/zhipu_source.py +6 -73
- astrbot/core/star/__init__.py +43 -11
- astrbot/core/star/config.py +17 -18
- astrbot/core/star/context.py +362 -138
- astrbot/core/star/filter/__init__.py +4 -3
- astrbot/core/star/filter/command.py +111 -35
- astrbot/core/star/filter/command_group.py +46 -34
- astrbot/core/star/filter/custom_filter.py +6 -5
- astrbot/core/star/filter/event_message_type.py +4 -2
- astrbot/core/star/filter/permission.py +4 -2
- astrbot/core/star/filter/platform_adapter_type.py +45 -12
- astrbot/core/star/filter/regex.py +4 -2
- astrbot/core/star/register/__init__.py +19 -15
- astrbot/core/star/register/star.py +41 -13
- astrbot/core/star/register/star_handler.py +236 -86
- astrbot/core/star/session_llm_manager.py +280 -0
- astrbot/core/star/session_plugin_manager.py +170 -0
- astrbot/core/star/star.py +36 -43
- astrbot/core/star/star_handler.py +47 -85
- astrbot/core/star/star_manager.py +442 -260
- astrbot/core/star/star_tools.py +167 -45
- astrbot/core/star/updator.py +17 -20
- astrbot/core/umop_config_router.py +106 -0
- astrbot/core/updator.py +38 -13
- astrbot/core/utils/astrbot_path.py +39 -0
- astrbot/core/utils/command_parser.py +1 -1
- astrbot/core/utils/io.py +119 -60
- astrbot/core/utils/log_pipe.py +1 -1
- astrbot/core/utils/metrics.py +11 -10
- astrbot/core/utils/migra_helper.py +73 -0
- astrbot/core/utils/path_util.py +63 -62
- astrbot/core/utils/pip_installer.py +37 -15
- astrbot/core/utils/session_lock.py +29 -0
- astrbot/core/utils/session_waiter.py +19 -20
- astrbot/core/utils/shared_preferences.py +174 -34
- astrbot/core/utils/t2i/__init__.py +4 -1
- astrbot/core/utils/t2i/local_strategy.py +386 -238
- astrbot/core/utils/t2i/network_strategy.py +109 -49
- astrbot/core/utils/t2i/renderer.py +29 -14
- astrbot/core/utils/t2i/template/astrbot_powershell.html +184 -0
- astrbot/core/utils/t2i/template_manager.py +111 -0
- astrbot/core/utils/tencent_record_helper.py +115 -1
- astrbot/core/utils/version_comparator.py +10 -13
- astrbot/core/zip_updator.py +112 -65
- astrbot/dashboard/routes/__init__.py +20 -13
- astrbot/dashboard/routes/auth.py +20 -9
- astrbot/dashboard/routes/chat.py +297 -141
- astrbot/dashboard/routes/config.py +652 -55
- astrbot/dashboard/routes/conversation.py +107 -37
- astrbot/dashboard/routes/file.py +26 -0
- astrbot/dashboard/routes/knowledge_base.py +1244 -0
- astrbot/dashboard/routes/log.py +27 -2
- astrbot/dashboard/routes/persona.py +202 -0
- astrbot/dashboard/routes/plugin.py +197 -139
- astrbot/dashboard/routes/route.py +27 -7
- astrbot/dashboard/routes/session_management.py +354 -0
- astrbot/dashboard/routes/stat.py +85 -18
- astrbot/dashboard/routes/static_file.py +5 -2
- astrbot/dashboard/routes/t2i.py +233 -0
- astrbot/dashboard/routes/tools.py +184 -120
- astrbot/dashboard/routes/update.py +59 -36
- astrbot/dashboard/server.py +96 -36
- astrbot/dashboard/utils.py +165 -0
- astrbot-4.7.0.dist-info/METADATA +294 -0
- astrbot-4.7.0.dist-info/RECORD +274 -0
- {astrbot-3.5.6.dist-info → astrbot-4.7.0.dist-info}/WHEEL +1 -1
- astrbot/core/db/plugin/sqlite_impl.py +0 -112
- astrbot/core/db/sqlite_init.sql +0 -50
- astrbot/core/pipeline/platform_compatibility/stage.py +0 -56
- astrbot/core/pipeline/process_stage/method/llm_request.py +0 -606
- astrbot/core/platform/sources/gewechat/client.py +0 -806
- astrbot/core/platform/sources/gewechat/downloader.py +0 -55
- astrbot/core/platform/sources/gewechat/gewechat_event.py +0 -255
- astrbot/core/platform/sources/gewechat/gewechat_platform_adapter.py +0 -103
- astrbot/core/platform/sources/gewechat/xml_data_parser.py +0 -110
- astrbot/core/provider/sources/dashscope_source.py +0 -203
- astrbot/core/provider/sources/dify_source.py +0 -281
- astrbot/core/provider/sources/llmtuner_source.py +0 -132
- astrbot/core/rag/embedding/openai_source.py +0 -20
- astrbot/core/rag/knowledge_db_mgr.py +0 -94
- astrbot/core/rag/store/__init__.py +0 -9
- astrbot/core/rag/store/chroma_db.py +0 -42
- astrbot/core/utils/dify_api_client.py +0 -152
- astrbot-3.5.6.dist-info/METADATA +0 -249
- astrbot-3.5.6.dist-info/RECORD +0 -158
- {astrbot-3.5.6.dist-info → astrbot-4.7.0.dist-info}/entry_points.txt +0 -0
- {astrbot-3.5.6.dist-info → astrbot-4.7.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,53 +1,97 @@
|
|
|
1
|
-
import time
|
|
2
1
|
import asyncio
|
|
3
|
-
import uuid
|
|
4
2
|
import os
|
|
5
|
-
|
|
3
|
+
import time
|
|
4
|
+
import uuid
|
|
5
|
+
from collections.abc import Awaitable, Callable
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from astrbot import logger
|
|
9
|
+
from astrbot.core.message.components import Image, Plain, Record
|
|
10
|
+
from astrbot.core.message.message_event_result import MessageChain
|
|
6
11
|
from astrbot.core.platform import (
|
|
7
|
-
Platform,
|
|
8
12
|
AstrBotMessage,
|
|
9
13
|
MessageMember,
|
|
10
14
|
MessageType,
|
|
15
|
+
Platform,
|
|
11
16
|
PlatformMetadata,
|
|
12
17
|
)
|
|
13
|
-
from astrbot.core.message.message_event_result import MessageChain
|
|
14
|
-
from astrbot.core.message.components import Plain, Image, Record # noqa: F403
|
|
15
|
-
from astrbot import logger
|
|
16
|
-
from astrbot.core import web_chat_queue
|
|
17
|
-
from .webchat_event import WebChatMessageEvent
|
|
18
18
|
from astrbot.core.platform.astr_message_event import MessageSesion
|
|
19
|
+
from astrbot.core.utils.astrbot_path import get_astrbot_data_path
|
|
20
|
+
|
|
19
21
|
from ...register import register_platform_adapter
|
|
22
|
+
from .webchat_event import WebChatMessageEvent
|
|
23
|
+
from .webchat_queue_mgr import WebChatQueueMgr, webchat_queue_mgr
|
|
20
24
|
|
|
21
25
|
|
|
22
26
|
class QueueListener:
|
|
23
|
-
def __init__(self,
|
|
24
|
-
self.
|
|
27
|
+
def __init__(self, webchat_queue_mgr: WebChatQueueMgr, callback: Callable) -> None:
|
|
28
|
+
self.webchat_queue_mgr = webchat_queue_mgr
|
|
25
29
|
self.callback = callback
|
|
30
|
+
self.running_tasks = set()
|
|
31
|
+
|
|
32
|
+
async def listen_to_queue(self, conversation_id: str):
|
|
33
|
+
"""Listen to a specific conversation queue"""
|
|
34
|
+
queue = self.webchat_queue_mgr.get_or_create_queue(conversation_id)
|
|
35
|
+
while True:
|
|
36
|
+
try:
|
|
37
|
+
data = await queue.get()
|
|
38
|
+
await self.callback(data)
|
|
39
|
+
except Exception as e:
|
|
40
|
+
logger.error(
|
|
41
|
+
f"Error processing message from conversation {conversation_id}: {e}",
|
|
42
|
+
)
|
|
43
|
+
break
|
|
26
44
|
|
|
27
45
|
async def run(self):
|
|
46
|
+
"""Monitor for new conversation queues and start listeners"""
|
|
47
|
+
monitored_conversations = set()
|
|
48
|
+
|
|
28
49
|
while True:
|
|
29
|
-
|
|
30
|
-
|
|
50
|
+
# Check for new conversations
|
|
51
|
+
current_conversations = set(self.webchat_queue_mgr.queues.keys())
|
|
52
|
+
new_conversations = current_conversations - monitored_conversations
|
|
53
|
+
|
|
54
|
+
# Start listeners for new conversations
|
|
55
|
+
for conversation_id in new_conversations:
|
|
56
|
+
task = asyncio.create_task(self.listen_to_queue(conversation_id))
|
|
57
|
+
self.running_tasks.add(task)
|
|
58
|
+
task.add_done_callback(self.running_tasks.discard)
|
|
59
|
+
monitored_conversations.add(conversation_id)
|
|
60
|
+
logger.debug(f"Started listener for conversation: {conversation_id}")
|
|
61
|
+
|
|
62
|
+
# Clean up monitored conversations that no longer exist
|
|
63
|
+
removed_conversations = monitored_conversations - current_conversations
|
|
64
|
+
monitored_conversations -= removed_conversations
|
|
65
|
+
|
|
66
|
+
await asyncio.sleep(1) # Check for new conversations every second
|
|
31
67
|
|
|
32
68
|
|
|
33
69
|
@register_platform_adapter("webchat", "webchat")
|
|
34
70
|
class WebChatAdapter(Platform):
|
|
35
71
|
def __init__(
|
|
36
|
-
self,
|
|
72
|
+
self,
|
|
73
|
+
platform_config: dict,
|
|
74
|
+
platform_settings: dict,
|
|
75
|
+
event_queue: asyncio.Queue,
|
|
37
76
|
) -> None:
|
|
38
77
|
super().__init__(event_queue)
|
|
39
78
|
|
|
40
79
|
self.config = platform_config
|
|
41
80
|
self.settings = platform_settings
|
|
42
81
|
self.unique_session = platform_settings["unique_session"]
|
|
43
|
-
self.imgs_dir = "
|
|
82
|
+
self.imgs_dir = os.path.join(get_astrbot_data_path(), "webchat", "imgs")
|
|
83
|
+
os.makedirs(self.imgs_dir, exist_ok=True)
|
|
44
84
|
|
|
45
85
|
self.metadata = PlatformMetadata(
|
|
46
|
-
name="webchat",
|
|
86
|
+
name="webchat",
|
|
87
|
+
description="webchat",
|
|
88
|
+
id="webchat",
|
|
47
89
|
)
|
|
48
90
|
|
|
49
91
|
async def send_by_session(
|
|
50
|
-
self,
|
|
92
|
+
self,
|
|
93
|
+
session: MessageSesion,
|
|
94
|
+
message_chain: MessageChain,
|
|
51
95
|
):
|
|
52
96
|
await WebChatMessageEvent._send(message_chain, session.session_id)
|
|
53
97
|
await super().send_by_session(session, message_chain)
|
|
@@ -57,7 +101,6 @@ class WebChatAdapter(Platform):
|
|
|
57
101
|
|
|
58
102
|
abm = AstrBotMessage()
|
|
59
103
|
abm.self_id = "webchat"
|
|
60
|
-
abm.tag = "webchat"
|
|
61
104
|
abm.sender = MessageMember(username, username)
|
|
62
105
|
|
|
63
106
|
abm.type = MessageType.FRIEND_MESSAGE
|
|
@@ -73,13 +116,13 @@ class WebChatAdapter(Platform):
|
|
|
73
116
|
if isinstance(payload["image_url"], list):
|
|
74
117
|
for img in payload["image_url"]:
|
|
75
118
|
abm.message.append(
|
|
76
|
-
Image.fromFileSystem(os.path.join(self.imgs_dir, img))
|
|
119
|
+
Image.fromFileSystem(os.path.join(self.imgs_dir, img)),
|
|
77
120
|
)
|
|
78
121
|
else:
|
|
79
122
|
abm.message.append(
|
|
80
123
|
Image.fromFileSystem(
|
|
81
|
-
os.path.join(self.imgs_dir, payload["image_url"])
|
|
82
|
-
)
|
|
124
|
+
os.path.join(self.imgs_dir, payload["image_url"]),
|
|
125
|
+
),
|
|
83
126
|
)
|
|
84
127
|
if payload["audio_url"]:
|
|
85
128
|
if isinstance(payload["audio_url"], list):
|
|
@@ -103,7 +146,7 @@ class WebChatAdapter(Platform):
|
|
|
103
146
|
abm = await self.convert_message(data)
|
|
104
147
|
await self.handle_msg(abm)
|
|
105
148
|
|
|
106
|
-
bot = QueueListener(
|
|
149
|
+
bot = QueueListener(webchat_queue_mgr, callback)
|
|
107
150
|
return bot.run()
|
|
108
151
|
|
|
109
152
|
def meta(self) -> PlatformMetadata:
|
|
@@ -117,6 +160,13 @@ class WebChatAdapter(Platform):
|
|
|
117
160
|
session_id=message.session_id,
|
|
118
161
|
)
|
|
119
162
|
|
|
163
|
+
_, _, payload = message.raw_message # type: ignore
|
|
164
|
+
message_event.set_extra("selected_provider", payload.get("selected_provider"))
|
|
165
|
+
message_event.set_extra("selected_model", payload.get("selected_model"))
|
|
166
|
+
message_event.set_extra(
|
|
167
|
+
"enable_streaming", payload.get("enable_streaming", True)
|
|
168
|
+
)
|
|
169
|
+
|
|
120
170
|
self.commit_event(message_event)
|
|
121
171
|
|
|
122
172
|
async def terminate(self):
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
import base64
|
|
1
2
|
import os
|
|
2
3
|
import uuid
|
|
3
|
-
|
|
4
|
+
|
|
4
5
|
from astrbot.api import logger
|
|
5
6
|
from astrbot.api.event import AstrMessageEvent, MessageChain
|
|
6
|
-
from astrbot.api.message_components import
|
|
7
|
+
from astrbot.api.message_components import Image, Plain, Record
|
|
8
|
+
from astrbot.core.utils.astrbot_path import get_astrbot_data_path
|
|
7
9
|
from astrbot.core.utils.io import download_image_by_url
|
|
8
|
-
from astrbot.core import web_chat_back_queue
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
from .webchat_queue_mgr import webchat_queue_mgr
|
|
12
|
+
|
|
13
|
+
imgs_dir = os.path.join(get_astrbot_data_path(), "webchat", "imgs")
|
|
11
14
|
|
|
12
15
|
|
|
13
16
|
class WebChatMessageEvent(AstrMessageEvent):
|
|
@@ -17,13 +20,18 @@ class WebChatMessageEvent(AstrMessageEvent):
|
|
|
17
20
|
|
|
18
21
|
@staticmethod
|
|
19
22
|
async def _send(message: MessageChain, session_id: str, streaming: bool = False):
|
|
23
|
+
cid = session_id.split("!")[-1]
|
|
24
|
+
web_chat_back_queue = webchat_queue_mgr.get_or_create_back_queue(cid)
|
|
20
25
|
if not message:
|
|
21
26
|
await web_chat_back_queue.put(
|
|
22
|
-
{
|
|
27
|
+
{
|
|
28
|
+
"type": "end",
|
|
29
|
+
"data": "",
|
|
30
|
+
"streaming": False,
|
|
31
|
+
}, # end means this request is finished
|
|
23
32
|
)
|
|
24
33
|
return ""
|
|
25
34
|
|
|
26
|
-
cid = session_id.split("!")[-1]
|
|
27
35
|
data = ""
|
|
28
36
|
for comp in message.chain:
|
|
29
37
|
if isinstance(comp, Plain):
|
|
@@ -34,7 +42,8 @@ class WebChatMessageEvent(AstrMessageEvent):
|
|
|
34
42
|
"cid": cid,
|
|
35
43
|
"data": data,
|
|
36
44
|
"streaming": streaming,
|
|
37
|
-
|
|
45
|
+
"chain_type": message.type,
|
|
46
|
+
},
|
|
38
47
|
)
|
|
39
48
|
elif isinstance(comp, Image):
|
|
40
49
|
# save image to local
|
|
@@ -63,7 +72,7 @@ class WebChatMessageEvent(AstrMessageEvent):
|
|
|
63
72
|
"cid": cid,
|
|
64
73
|
"data": data,
|
|
65
74
|
"streaming": streaming,
|
|
66
|
-
}
|
|
75
|
+
},
|
|
67
76
|
)
|
|
68
77
|
elif isinstance(comp, Record):
|
|
69
78
|
# save record to local
|
|
@@ -87,7 +96,7 @@ class WebChatMessageEvent(AstrMessageEvent):
|
|
|
87
96
|
"cid": cid,
|
|
88
97
|
"data": data,
|
|
89
98
|
"streaming": streaming,
|
|
90
|
-
}
|
|
99
|
+
},
|
|
91
100
|
)
|
|
92
101
|
else:
|
|
93
102
|
logger.debug(f"webchat 忽略: {comp.type}")
|
|
@@ -96,29 +105,44 @@ class WebChatMessageEvent(AstrMessageEvent):
|
|
|
96
105
|
|
|
97
106
|
async def send(self, message: MessageChain):
|
|
98
107
|
await WebChatMessageEvent._send(message, session_id=self.session_id)
|
|
99
|
-
await web_chat_back_queue.put(
|
|
100
|
-
{
|
|
101
|
-
"type": "end",
|
|
102
|
-
"data": "",
|
|
103
|
-
"streaming": False,
|
|
104
|
-
"cid": self.session_id.split("!")[-1],
|
|
105
|
-
}
|
|
106
|
-
)
|
|
107
108
|
await super().send(message)
|
|
108
109
|
|
|
109
110
|
async def send_streaming(self, generator, use_fallback: bool = False):
|
|
110
111
|
final_data = ""
|
|
112
|
+
reasoning_content = ""
|
|
113
|
+
cid = self.session_id.split("!")[-1]
|
|
114
|
+
web_chat_back_queue = webchat_queue_mgr.get_or_create_back_queue(cid)
|
|
111
115
|
async for chain in generator:
|
|
112
|
-
|
|
113
|
-
|
|
116
|
+
if chain.type == "break" and final_data:
|
|
117
|
+
# 分割符
|
|
118
|
+
await web_chat_back_queue.put(
|
|
119
|
+
{
|
|
120
|
+
"type": "break", # break means a segment end
|
|
121
|
+
"data": final_data,
|
|
122
|
+
"streaming": True,
|
|
123
|
+
"cid": cid,
|
|
124
|
+
},
|
|
125
|
+
)
|
|
126
|
+
final_data = ""
|
|
127
|
+
continue
|
|
128
|
+
|
|
129
|
+
r = await WebChatMessageEvent._send(
|
|
130
|
+
chain,
|
|
131
|
+
session_id=self.session_id,
|
|
132
|
+
streaming=True,
|
|
114
133
|
)
|
|
134
|
+
if chain.type == "reasoning":
|
|
135
|
+
reasoning_content += chain.get_plain_text()
|
|
136
|
+
else:
|
|
137
|
+
final_data += r
|
|
115
138
|
|
|
116
139
|
await web_chat_back_queue.put(
|
|
117
140
|
{
|
|
118
|
-
"type": "
|
|
141
|
+
"type": "complete", # complete means we return the final result
|
|
119
142
|
"data": final_data,
|
|
143
|
+
"reasoning": reasoning_content,
|
|
120
144
|
"streaming": True,
|
|
121
|
-
"cid":
|
|
122
|
-
}
|
|
145
|
+
"cid": cid,
|
|
146
|
+
},
|
|
123
147
|
)
|
|
124
148
|
await super().send_streaming(generator, use_fallback)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class WebChatQueueMgr:
|
|
5
|
+
def __init__(self) -> None:
|
|
6
|
+
self.queues = {}
|
|
7
|
+
"""Conversation ID to asyncio.Queue mapping"""
|
|
8
|
+
self.back_queues = {}
|
|
9
|
+
"""Conversation ID to asyncio.Queue mapping for responses"""
|
|
10
|
+
|
|
11
|
+
def get_or_create_queue(self, conversation_id: str) -> asyncio.Queue:
|
|
12
|
+
"""Get or create a queue for the given conversation ID"""
|
|
13
|
+
if conversation_id not in self.queues:
|
|
14
|
+
self.queues[conversation_id] = asyncio.Queue()
|
|
15
|
+
return self.queues[conversation_id]
|
|
16
|
+
|
|
17
|
+
def get_or_create_back_queue(self, conversation_id: str) -> asyncio.Queue:
|
|
18
|
+
"""Get or create a back queue for the given conversation ID"""
|
|
19
|
+
if conversation_id not in self.back_queues:
|
|
20
|
+
self.back_queues[conversation_id] = asyncio.Queue()
|
|
21
|
+
return self.back_queues[conversation_id]
|
|
22
|
+
|
|
23
|
+
def remove_queues(self, conversation_id: str):
|
|
24
|
+
"""Remove queues for the given conversation ID"""
|
|
25
|
+
if conversation_id in self.queues:
|
|
26
|
+
del self.queues[conversation_id]
|
|
27
|
+
if conversation_id in self.back_queues:
|
|
28
|
+
del self.back_queues[conversation_id]
|
|
29
|
+
|
|
30
|
+
def has_queue(self, conversation_id: str) -> bool:
|
|
31
|
+
"""Check if a queue exists for the given conversation ID"""
|
|
32
|
+
return conversation_id in self.queues
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
webchat_queue_mgr = WebChatQueueMgr()
|