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
astrbot/core/db/__init__.py
CHANGED
|
@@ -1,161 +1,364 @@
|
|
|
1
1
|
import abc
|
|
2
|
+
import datetime
|
|
3
|
+
import typing as T
|
|
4
|
+
from contextlib import asynccontextmanager
|
|
2
5
|
from dataclasses import dataclass
|
|
3
|
-
|
|
4
|
-
from
|
|
6
|
+
|
|
7
|
+
from deprecated import deprecated
|
|
8
|
+
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
|
|
9
|
+
from sqlalchemy.orm import sessionmaker
|
|
10
|
+
|
|
11
|
+
from astrbot.core.db.po import (
|
|
12
|
+
Attachment,
|
|
13
|
+
ConversationV2,
|
|
14
|
+
Persona,
|
|
15
|
+
PlatformMessageHistory,
|
|
16
|
+
PlatformSession,
|
|
17
|
+
PlatformStat,
|
|
18
|
+
Preference,
|
|
19
|
+
Stats,
|
|
20
|
+
)
|
|
5
21
|
|
|
6
22
|
|
|
7
23
|
@dataclass
|
|
8
24
|
class BaseDatabase(abc.ABC):
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
""
|
|
25
|
+
"""数据库基类"""
|
|
26
|
+
|
|
27
|
+
DATABASE_URL = ""
|
|
12
28
|
|
|
13
29
|
def __init__(self) -> None:
|
|
14
|
-
|
|
30
|
+
self.engine = create_async_engine(
|
|
31
|
+
self.DATABASE_URL,
|
|
32
|
+
echo=False,
|
|
33
|
+
future=True,
|
|
34
|
+
)
|
|
35
|
+
self.AsyncSessionLocal = sessionmaker(
|
|
36
|
+
self.engine,
|
|
37
|
+
class_=AsyncSession,
|
|
38
|
+
expire_on_commit=False,
|
|
39
|
+
)
|
|
15
40
|
|
|
16
|
-
def
|
|
17
|
-
"""
|
|
18
|
-
self.insert_platform_metrics(metrics["platform_stats"])
|
|
19
|
-
self.insert_plugin_metrics(metrics["plugin_stats"])
|
|
20
|
-
self.insert_command_metrics(metrics["command_stats"])
|
|
21
|
-
self.insert_llm_metrics(metrics["llm_stats"])
|
|
41
|
+
async def initialize(self):
|
|
42
|
+
"""初始化数据库连接"""
|
|
22
43
|
|
|
44
|
+
@asynccontextmanager
|
|
45
|
+
async def get_db(self) -> T.AsyncGenerator[AsyncSession, None]:
|
|
46
|
+
"""Get a database session."""
|
|
47
|
+
if not self.inited:
|
|
48
|
+
await self.initialize()
|
|
49
|
+
self.inited = True
|
|
50
|
+
async with self.AsyncSessionLocal() as session:
|
|
51
|
+
yield session
|
|
52
|
+
|
|
53
|
+
@deprecated(version="4.0.0", reason="Use get_platform_stats instead")
|
|
23
54
|
@abc.abstractmethod
|
|
24
|
-
def
|
|
25
|
-
"""
|
|
55
|
+
def get_base_stats(self, offset_sec: int = 86400) -> Stats:
|
|
56
|
+
"""获取基础统计数据"""
|
|
26
57
|
raise NotImplementedError
|
|
27
58
|
|
|
59
|
+
@deprecated(version="4.0.0", reason="Use get_platform_stats instead")
|
|
28
60
|
@abc.abstractmethod
|
|
29
|
-
def
|
|
30
|
-
"""
|
|
61
|
+
def get_total_message_count(self) -> int:
|
|
62
|
+
"""获取总消息数"""
|
|
31
63
|
raise NotImplementedError
|
|
32
64
|
|
|
65
|
+
@deprecated(version="4.0.0", reason="Use get_platform_stats instead")
|
|
33
66
|
@abc.abstractmethod
|
|
34
|
-
def
|
|
35
|
-
"""
|
|
67
|
+
def get_grouped_base_stats(self, offset_sec: int = 86400) -> Stats:
|
|
68
|
+
"""获取基础统计数据(合并)"""
|
|
36
69
|
raise NotImplementedError
|
|
37
70
|
|
|
71
|
+
# New methods in v4.0.0
|
|
72
|
+
|
|
38
73
|
@abc.abstractmethod
|
|
39
|
-
def
|
|
40
|
-
|
|
41
|
-
|
|
74
|
+
async def insert_platform_stats(
|
|
75
|
+
self,
|
|
76
|
+
platform_id: str,
|
|
77
|
+
platform_type: str,
|
|
78
|
+
count: int = 1,
|
|
79
|
+
timestamp: datetime.datetime | None = None,
|
|
80
|
+
) -> None:
|
|
81
|
+
"""Insert a new platform statistic record."""
|
|
82
|
+
...
|
|
42
83
|
|
|
43
84
|
@abc.abstractmethod
|
|
44
|
-
def
|
|
45
|
-
"""
|
|
46
|
-
|
|
85
|
+
async def count_platform_stats(self) -> int:
|
|
86
|
+
"""Count the number of platform statistics records."""
|
|
87
|
+
...
|
|
47
88
|
|
|
48
89
|
@abc.abstractmethod
|
|
49
|
-
def
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"""获取 LLM 历史记录, 如果 session_id 为 None, 返回所有"""
|
|
53
|
-
raise NotImplementedError
|
|
90
|
+
async def get_platform_stats(self, offset_sec: int = 86400) -> list[PlatformStat]:
|
|
91
|
+
"""Get platform statistics within the specified offset in seconds and group by platform_id."""
|
|
92
|
+
...
|
|
54
93
|
|
|
55
94
|
@abc.abstractmethod
|
|
56
|
-
def
|
|
57
|
-
|
|
58
|
-
|
|
95
|
+
async def get_conversations(
|
|
96
|
+
self,
|
|
97
|
+
user_id: str | None = None,
|
|
98
|
+
platform_id: str | None = None,
|
|
99
|
+
) -> list[ConversationV2]:
|
|
100
|
+
"""Get all conversations for a specific user and platform_id(optional).
|
|
101
|
+
|
|
102
|
+
content is not included in the result.
|
|
103
|
+
"""
|
|
104
|
+
...
|
|
59
105
|
|
|
60
106
|
@abc.abstractmethod
|
|
61
|
-
def
|
|
62
|
-
"""
|
|
63
|
-
|
|
107
|
+
async def get_conversation_by_id(self, cid: str) -> ConversationV2:
|
|
108
|
+
"""Get a specific conversation by its ID."""
|
|
109
|
+
...
|
|
64
110
|
|
|
65
111
|
@abc.abstractmethod
|
|
66
|
-
def
|
|
67
|
-
|
|
68
|
-
|
|
112
|
+
async def get_all_conversations(
|
|
113
|
+
self,
|
|
114
|
+
page: int = 1,
|
|
115
|
+
page_size: int = 20,
|
|
116
|
+
) -> list[ConversationV2]:
|
|
117
|
+
"""Get all conversations with pagination."""
|
|
118
|
+
...
|
|
69
119
|
|
|
70
120
|
@abc.abstractmethod
|
|
71
|
-
def
|
|
72
|
-
|
|
73
|
-
|
|
121
|
+
async def get_filtered_conversations(
|
|
122
|
+
self,
|
|
123
|
+
page: int = 1,
|
|
124
|
+
page_size: int = 20,
|
|
125
|
+
platform_ids: list[str] | None = None,
|
|
126
|
+
search_query: str = "",
|
|
127
|
+
**kwargs,
|
|
128
|
+
) -> tuple[list[ConversationV2], int]:
|
|
129
|
+
"""Get conversations filtered by platform IDs and search query."""
|
|
130
|
+
...
|
|
74
131
|
|
|
75
132
|
@abc.abstractmethod
|
|
76
|
-
def
|
|
77
|
-
|
|
78
|
-
|
|
133
|
+
async def create_conversation(
|
|
134
|
+
self,
|
|
135
|
+
user_id: str,
|
|
136
|
+
platform_id: str,
|
|
137
|
+
content: list[dict] | None = None,
|
|
138
|
+
title: str | None = None,
|
|
139
|
+
persona_id: str | None = None,
|
|
140
|
+
cid: str | None = None,
|
|
141
|
+
created_at: datetime.datetime | None = None,
|
|
142
|
+
updated_at: datetime.datetime | None = None,
|
|
143
|
+
) -> ConversationV2:
|
|
144
|
+
"""Create a new conversation."""
|
|
145
|
+
...
|
|
79
146
|
|
|
80
147
|
@abc.abstractmethod
|
|
81
|
-
def
|
|
82
|
-
self,
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
148
|
+
async def update_conversation(
|
|
149
|
+
self,
|
|
150
|
+
cid: str,
|
|
151
|
+
title: str | None = None,
|
|
152
|
+
persona_id: str | None = None,
|
|
153
|
+
content: list[dict] | None = None,
|
|
154
|
+
) -> None:
|
|
155
|
+
"""Update a conversation's history."""
|
|
156
|
+
...
|
|
86
157
|
|
|
87
158
|
@abc.abstractmethod
|
|
88
|
-
def
|
|
89
|
-
"""
|
|
90
|
-
|
|
159
|
+
async def delete_conversation(self, cid: str) -> None:
|
|
160
|
+
"""Delete a conversation by its ID."""
|
|
161
|
+
...
|
|
91
162
|
|
|
92
163
|
@abc.abstractmethod
|
|
93
|
-
def
|
|
94
|
-
"""
|
|
95
|
-
|
|
164
|
+
async def delete_conversations_by_user_id(self, user_id: str) -> None:
|
|
165
|
+
"""Delete all conversations for a specific user."""
|
|
166
|
+
...
|
|
96
167
|
|
|
97
168
|
@abc.abstractmethod
|
|
98
|
-
def
|
|
99
|
-
|
|
169
|
+
async def insert_platform_message_history(
|
|
170
|
+
self,
|
|
171
|
+
platform_id: str,
|
|
172
|
+
user_id: str,
|
|
173
|
+
content: dict,
|
|
174
|
+
sender_id: str | None = None,
|
|
175
|
+
sender_name: str | None = None,
|
|
176
|
+
) -> None:
|
|
177
|
+
"""Insert a new platform message history record."""
|
|
178
|
+
...
|
|
100
179
|
|
|
101
180
|
@abc.abstractmethod
|
|
102
|
-
def
|
|
103
|
-
|
|
104
|
-
|
|
181
|
+
async def delete_platform_message_offset(
|
|
182
|
+
self,
|
|
183
|
+
platform_id: str,
|
|
184
|
+
user_id: str,
|
|
185
|
+
offset_sec: int = 86400,
|
|
186
|
+
) -> None:
|
|
187
|
+
"""Delete platform message history records newer than the specified offset."""
|
|
188
|
+
...
|
|
105
189
|
|
|
106
190
|
@abc.abstractmethod
|
|
107
|
-
def
|
|
108
|
-
|
|
109
|
-
|
|
191
|
+
async def get_platform_message_history(
|
|
192
|
+
self,
|
|
193
|
+
platform_id: str,
|
|
194
|
+
user_id: str,
|
|
195
|
+
page: int = 1,
|
|
196
|
+
page_size: int = 20,
|
|
197
|
+
) -> list[PlatformMessageHistory]:
|
|
198
|
+
"""Get platform message history for a specific user."""
|
|
199
|
+
...
|
|
110
200
|
|
|
111
201
|
@abc.abstractmethod
|
|
112
|
-
def
|
|
113
|
-
|
|
114
|
-
|
|
202
|
+
async def insert_attachment(
|
|
203
|
+
self,
|
|
204
|
+
path: str,
|
|
205
|
+
type: str,
|
|
206
|
+
mime_type: str,
|
|
207
|
+
):
|
|
208
|
+
"""Insert a new attachment record."""
|
|
209
|
+
...
|
|
115
210
|
|
|
116
211
|
@abc.abstractmethod
|
|
117
|
-
def
|
|
118
|
-
"""
|
|
119
|
-
|
|
212
|
+
async def get_attachment_by_id(self, attachment_id: str) -> Attachment:
|
|
213
|
+
"""Get an attachment by its ID."""
|
|
214
|
+
...
|
|
215
|
+
|
|
216
|
+
@abc.abstractmethod
|
|
217
|
+
async def insert_persona(
|
|
218
|
+
self,
|
|
219
|
+
persona_id: str,
|
|
220
|
+
system_prompt: str,
|
|
221
|
+
begin_dialogs: list[str] | None = None,
|
|
222
|
+
tools: list[str] | None = None,
|
|
223
|
+
) -> Persona:
|
|
224
|
+
"""Insert a new persona record."""
|
|
225
|
+
...
|
|
120
226
|
|
|
121
227
|
@abc.abstractmethod
|
|
122
|
-
def
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
"""获取所有对话,支持分页
|
|
228
|
+
async def get_persona_by_id(self, persona_id: str) -> Persona:
|
|
229
|
+
"""Get a persona by its ID."""
|
|
230
|
+
...
|
|
126
231
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
232
|
+
@abc.abstractmethod
|
|
233
|
+
async def get_personas(self) -> list[Persona]:
|
|
234
|
+
"""Get all personas for a specific bot."""
|
|
235
|
+
...
|
|
130
236
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
237
|
+
@abc.abstractmethod
|
|
238
|
+
async def update_persona(
|
|
239
|
+
self,
|
|
240
|
+
persona_id: str,
|
|
241
|
+
system_prompt: str | None = None,
|
|
242
|
+
begin_dialogs: list[str] | None = None,
|
|
243
|
+
tools: list[str] | None = None,
|
|
244
|
+
) -> Persona | None:
|
|
245
|
+
"""Update a persona's system prompt or begin dialogs."""
|
|
246
|
+
...
|
|
247
|
+
|
|
248
|
+
@abc.abstractmethod
|
|
249
|
+
async def delete_persona(self, persona_id: str) -> None:
|
|
250
|
+
"""Delete a persona by its ID."""
|
|
251
|
+
...
|
|
252
|
+
|
|
253
|
+
@abc.abstractmethod
|
|
254
|
+
async def insert_preference_or_update(
|
|
255
|
+
self,
|
|
256
|
+
scope: str,
|
|
257
|
+
scope_id: str,
|
|
258
|
+
key: str,
|
|
259
|
+
value: dict,
|
|
260
|
+
) -> Preference:
|
|
261
|
+
"""Insert a new preference record."""
|
|
262
|
+
...
|
|
263
|
+
|
|
264
|
+
@abc.abstractmethod
|
|
265
|
+
async def get_preference(self, scope: str, scope_id: str, key: str) -> Preference:
|
|
266
|
+
"""Get a preference by scope ID and key."""
|
|
267
|
+
...
|
|
268
|
+
|
|
269
|
+
@abc.abstractmethod
|
|
270
|
+
async def get_preferences(
|
|
271
|
+
self,
|
|
272
|
+
scope: str,
|
|
273
|
+
scope_id: str | None = None,
|
|
274
|
+
key: str | None = None,
|
|
275
|
+
) -> list[Preference]:
|
|
276
|
+
"""Get all preferences for a specific scope ID or key."""
|
|
277
|
+
...
|
|
278
|
+
|
|
279
|
+
@abc.abstractmethod
|
|
280
|
+
async def remove_preference(self, scope: str, scope_id: str, key: str) -> None:
|
|
281
|
+
"""Remove a preference by scope ID and key."""
|
|
282
|
+
...
|
|
283
|
+
|
|
284
|
+
@abc.abstractmethod
|
|
285
|
+
async def clear_preferences(self, scope: str, scope_id: str) -> None:
|
|
286
|
+
"""Clear all preferences for a specific scope ID."""
|
|
287
|
+
...
|
|
288
|
+
|
|
289
|
+
# @abc.abstractmethod
|
|
290
|
+
# async def insert_llm_message(
|
|
291
|
+
# self,
|
|
292
|
+
# cid: str,
|
|
293
|
+
# role: str,
|
|
294
|
+
# content: list,
|
|
295
|
+
# tool_calls: list = None,
|
|
296
|
+
# tool_call_id: str = None,
|
|
297
|
+
# parent_id: str = None,
|
|
298
|
+
# ) -> LLMMessage:
|
|
299
|
+
# """Insert a new LLM message into the conversation."""
|
|
300
|
+
# ...
|
|
301
|
+
|
|
302
|
+
# @abc.abstractmethod
|
|
303
|
+
# async def get_llm_messages(self, cid: str) -> list[LLMMessage]:
|
|
304
|
+
# """Get all LLM messages for a specific conversation."""
|
|
305
|
+
# ...
|
|
135
306
|
|
|
136
307
|
@abc.abstractmethod
|
|
137
|
-
def
|
|
308
|
+
async def get_session_conversations(
|
|
138
309
|
self,
|
|
139
310
|
page: int = 1,
|
|
140
311
|
page_size: int = 20,
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
"""
|
|
161
|
-
|
|
312
|
+
search_query: str | None = None,
|
|
313
|
+
platform: str | None = None,
|
|
314
|
+
) -> tuple[list[dict], int]:
|
|
315
|
+
"""Get paginated session conversations with joined conversation and persona details, support search and platform filter."""
|
|
316
|
+
...
|
|
317
|
+
|
|
318
|
+
# ====
|
|
319
|
+
# Platform Session Management
|
|
320
|
+
# ====
|
|
321
|
+
|
|
322
|
+
@abc.abstractmethod
|
|
323
|
+
async def create_platform_session(
|
|
324
|
+
self,
|
|
325
|
+
creator: str,
|
|
326
|
+
platform_id: str = "webchat",
|
|
327
|
+
session_id: str | None = None,
|
|
328
|
+
display_name: str | None = None,
|
|
329
|
+
is_group: int = 0,
|
|
330
|
+
) -> PlatformSession:
|
|
331
|
+
"""Create a new Platform session."""
|
|
332
|
+
...
|
|
333
|
+
|
|
334
|
+
@abc.abstractmethod
|
|
335
|
+
async def get_platform_session_by_id(
|
|
336
|
+
self, session_id: str
|
|
337
|
+
) -> PlatformSession | None:
|
|
338
|
+
"""Get a Platform session by its ID."""
|
|
339
|
+
...
|
|
340
|
+
|
|
341
|
+
@abc.abstractmethod
|
|
342
|
+
async def get_platform_sessions_by_creator(
|
|
343
|
+
self,
|
|
344
|
+
creator: str,
|
|
345
|
+
platform_id: str | None = None,
|
|
346
|
+
page: int = 1,
|
|
347
|
+
page_size: int = 20,
|
|
348
|
+
) -> list[PlatformSession]:
|
|
349
|
+
"""Get all Platform sessions for a specific creator (username) and optionally platform."""
|
|
350
|
+
...
|
|
351
|
+
|
|
352
|
+
@abc.abstractmethod
|
|
353
|
+
async def update_platform_session(
|
|
354
|
+
self,
|
|
355
|
+
session_id: str,
|
|
356
|
+
display_name: str | None = None,
|
|
357
|
+
) -> None:
|
|
358
|
+
"""Update a Platform session's updated_at timestamp and optionally display_name."""
|
|
359
|
+
...
|
|
360
|
+
|
|
361
|
+
@abc.abstractmethod
|
|
362
|
+
async def delete_platform_session(self, session_id: str) -> None:
|
|
363
|
+
"""Delete a Platform session by its ID."""
|
|
364
|
+
...
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from astrbot.api import logger, sp
|
|
4
|
+
from astrbot.core.config import AstrBotConfig
|
|
5
|
+
from astrbot.core.db import BaseDatabase
|
|
6
|
+
from astrbot.core.utils.astrbot_path import get_astrbot_data_path
|
|
7
|
+
|
|
8
|
+
from .migra_3_to_4 import (
|
|
9
|
+
migration_conversation_table,
|
|
10
|
+
migration_persona_data,
|
|
11
|
+
migration_platform_table,
|
|
12
|
+
migration_preferences,
|
|
13
|
+
migration_webchat_data,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
async def check_migration_needed_v4(db_helper: BaseDatabase) -> bool:
|
|
18
|
+
"""检查是否需要进行数据库迁移
|
|
19
|
+
如果存在 data_v3.db 并且 preference 中没有 migration_done_v4,则需要进行迁移。
|
|
20
|
+
"""
|
|
21
|
+
# 仅当 data 目录下存在旧版本数据(data_v3.db 文件)时才考虑迁移
|
|
22
|
+
data_dir = get_astrbot_data_path()
|
|
23
|
+
data_v3_db = os.path.join(data_dir, "data_v3.db")
|
|
24
|
+
|
|
25
|
+
if not os.path.exists(data_v3_db):
|
|
26
|
+
return False
|
|
27
|
+
migration_done = await db_helper.get_preference(
|
|
28
|
+
"global",
|
|
29
|
+
"global",
|
|
30
|
+
"migration_done_v4",
|
|
31
|
+
)
|
|
32
|
+
if migration_done:
|
|
33
|
+
return False
|
|
34
|
+
return True
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
async def do_migration_v4(
|
|
38
|
+
db_helper: BaseDatabase,
|
|
39
|
+
platform_id_map: dict[str, dict[str, str]],
|
|
40
|
+
astrbot_config: AstrBotConfig,
|
|
41
|
+
) -> None:
|
|
42
|
+
"""执行数据库迁移
|
|
43
|
+
迁移旧的 webchat_conversation 表到新的 conversation 表。
|
|
44
|
+
迁移旧的 platform 到新的 platform_stats 表。
|
|
45
|
+
"""
|
|
46
|
+
if not await check_migration_needed_v4(db_helper):
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
logger.info("开始执行数据库迁移...")
|
|
50
|
+
|
|
51
|
+
# 执行会话表迁移
|
|
52
|
+
await migration_conversation_table(db_helper, platform_id_map)
|
|
53
|
+
|
|
54
|
+
# 执行人格数据迁移
|
|
55
|
+
await migration_persona_data(db_helper, astrbot_config)
|
|
56
|
+
|
|
57
|
+
# 执行 WebChat 数据迁移
|
|
58
|
+
await migration_webchat_data(db_helper, platform_id_map)
|
|
59
|
+
|
|
60
|
+
# 执行偏好设置迁移
|
|
61
|
+
await migration_preferences(db_helper, platform_id_map)
|
|
62
|
+
|
|
63
|
+
# 执行平台统计表迁移
|
|
64
|
+
await migration_platform_table(db_helper, platform_id_map)
|
|
65
|
+
|
|
66
|
+
# 标记迁移完成
|
|
67
|
+
await sp.put_async("global", "global", "migration_done_v4", True)
|
|
68
|
+
|
|
69
|
+
logger.info("数据库迁移完成。")
|