Add HeXi bot codebase: custom plugins, web frontends, tests

- hexi core: message handling, rate limiting, cooldown, plugin manager
- Custom plugins: BF stats, daily check-in, quotes, persona cards, etc.
- Community plugins vendored under hexi/plugins with local fixes
- Web admin frontends (learning-chat, persona-admin), unified hexi/web
- Tests for rate_limit/cooldown/memes/persona; poetry.lock

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-09-01 13:13:40 +08:00
co-authored by Claude
parent 1783c60afa
commit b61d09f09f
3201 changed files with 160436 additions and 171 deletions
@@ -0,0 +1,125 @@
"""NoneBot 版服务装配与执行入口。"""
from __future__ import annotations
from typing import Any
from .adapter import OneBotAdapter
from .bot_manager import BotManager
from .config import ConfigDict, load_config
from .core.application.services.analysis_application_service import (
AnalysisApplicationService,
)
from .core.domain.services.analysis_domain_service import AnalysisDomainService
from .core.domain.services.incremental_merge_service import IncrementalMergeService
from .core.domain.services.statistics_service import StatisticsService
from .core.infrastructure.analysis.llm_analyzer import LLMAnalyzer
from .core.infrastructure.config.config_manager import ConfigManager
from .core.infrastructure.persistence.checkpoint_store import CheckpointStore
from .core.infrastructure.persistence.history_manager import HistoryManager
from .core.infrastructure.persistence.incremental_store import IncrementalStore
from .core.infrastructure.reporting.generators import ReportGenerator
from .core.infrastructure.visualization.activity_charts import ActivityVisualizer
from .core.shared.constants import PLUGIN_NAME
from .core.shared.trace_context import TraceContext
from .core.utils.logger import logger
from .core.utils.paths import get_data_dir
from .kv_store import AsyncKVStore
from .renderer import html_render
_services: dict[str, Any] | None = None
class _DummyContext:
"""替代 AstrBot Context;本插件的 LLM 层不再使用它。"""
def get_provider_by_id(self, **kwargs):
return None
def get_all_providers(self):
return []
async def get_current_chat_provider_id(self, **kwargs):
return None
async def llm_generate(self, **kwargs):
raise NotImplementedError
def _build_services() -> dict[str, Any]:
global _services
if _services is not None:
return _services
cfg = load_config()
config_manager = ConfigManager(cfg)
data_dir = get_data_dir(PLUGIN_NAME)
data_dir.mkdir(parents=True, exist_ok=True)
kv_store = AsyncKVStore(data_dir / "kv_store.json")
activity_visualizer = ActivityVisualizer()
statistics_service = StatisticsService(activity_visualizer)
analysis_domain_service = AnalysisDomainService()
incremental_merge_service = IncrementalMergeService()
report_generator = ReportGenerator(config_manager, data_dir)
llm_analyzer = LLMAnalyzer(_DummyContext(), config_manager)
history_manager = HistoryManager(kv_store)
incremental_store = IncrementalStore(kv_store)
checkpoint_store = CheckpointStore(data_dir / "traces.db")
# 登记 TraceContext 持久化(可选,不影响分析主链路)
try:
from .core.infrastructure.persistence.trace_sqlite_store import TraceSQLiteStore
TraceContext.set_global_store(TraceSQLiteStore(data_dir / "traces.db"))
except Exception as e:
logger.debug(f"TraceStore 初始化失败(忽略): {e}")
bot_manager = BotManager()
analysis_service = AnalysisApplicationService(
config_manager=config_manager,
bot_manager=bot_manager,
history_manager=history_manager,
report_generator=report_generator,
llm_analyzer=llm_analyzer,
statistics_service=statistics_service,
analysis_domain_service=analysis_domain_service,
incremental_store=incremental_store,
incremental_merge_service=incremental_merge_service,
checkpoint_store=checkpoint_store,
html_render=html_render,
)
_services = {
"config_manager": config_manager,
"report_generator": report_generator,
"analysis_service": analysis_service,
"bot_manager": bot_manager,
"data_dir": data_dir,
}
return _services
def get_services() -> dict[str, Any]:
return _build_services()
def register_bot_adapter(bot: Any, platform_id: str | None = None) -> OneBotAdapter:
"""为当前 Bot 注册/更新 OneBot 适配器。"""
svc = _build_services()
bot_manager = svc["bot_manager"]
config_manager = svc["config_manager"]
bot_self_ids = list(config_manager.get_bot_self_ids() or [])
adapter = OneBotAdapter(
bot,
{
"platform_id": platform_id or "onebot",
"bot_self_ids": bot_self_ids,
"filter_bot_messages": config_manager.get_filter_bot_messages(),
},
)
bot_manager.register_adapter(adapter, platform_id or "onebot")
return adapter