nagisa-core 0.6.1

Nagisa framework core: Bot, EventSource/ActionInvoker traits, dispatch engine
Documentation

Nagisa 框架运行时核心:统一 [Bot] 句柄、[EventSource]/ActionInvoker 两个传输 trait,以及把二者串起来的 dispatch 引擎。

adapter(nagisa-onebot / nagisa-milky)实现这两个 trait,把协议 wire 翻译进出 nagisa-types 的统一类型;业务 / 上层门面(nagisa crate 的 App)只面向本 crate 的抽象。

模块地图

传输与运行:

  • [source]:入站事件源 trait(EventSource)。
  • [bot] / [invoker] / [refs] / [impl_info]:出站动作。[Bot] 是廉价克隆的句柄, 内含 Arc<dyn Actions>;[invoker] 把动作分三层(ActionInvoker 两协议通用、OneBotActions OneBot 独有 + 厂商扩展、 MilkyActions Milky 独有),[refs] 是按目标分组的句柄糖。
  • [dispatch]:消费事件流、逐个构造 [Ctx]、并发分发给 [Router]。
  • [reconnect]:带上限指数退避的重连循环 helper(adapter 用)。
  • [sse]:纯字节级 SSE 解析器(adapter 用)。
  • [wire]:两适配器共用的 wire 基建——log_wire 协议帧日志、零依赖 base64、HTTP 动作通道 骨架(adapter 用)。
  • [framesource]:连接后的公共泵骨架——FrameSource/Frame/pump(adapter 用)。
  • [service]:服务生命周期 Supervisor + 依赖 DAG + ServiceBus,门面据此搭线。

分发与匹配(路1:声明式 handler):

  • [ctx]:每事件上下文 Ctx(提取器从它取料)。
  • [router]:handler 注册表 + app 共享状态 + 洋葱中间件 + 三层分发。
  • [handler] / [extract] / [args] / [slots]:handler 抽象 + FromContext 提取器 + 声明式参数(TAIL 段流)/ 命名 slot(HEAD 捕获组)解析。
  • [matcher]:命令触发匹配器(字面量 / 正则 / 有序 slot)+ MentionMe 预处理。
  • [rule]:可组合门控 Rule&/|/! 代数)+ 权限 / 场景 / kill-switch / 休眠叶子。
  • [middleware] / [ratelimit]:洋葱中间件 + 内置限流。
  • [cooldown]:冷却门控(声明式 Rule + 命令式 Cd 句柄)。

插件与开关:

  • [plugin] / [registry]:inventory 编译期收集的插件 / 触发器静态模型。
  • [enabled]:分层启用 / 禁用状态(插件总开关 + 触发器子开关,按会话覆盖)。
  • [event_trigger]:EventKind 判别式 + 细粒度事件提取器(#[event(Kind)] 用)。

交互(路2:命令式 waiter / session):

  • [session]:Session/Waiter 中断引擎 + single_flight
  • [rendezvous]:跨会话「留 token、稍后取」的 TTL 存储。

派发模型:事件 → router → gate → handler

[dispatch::run_dispatch] 从 [EventSource] 收事件,每个事件在独立 tokio 任务里 构造一个 [Ctx](共享 router 状态 + bot),交给 [Router::dispatch]。router 先穿过 洋葱中间件链,末端跑三层 handler(见 [Router]):

  1. top observeron_top):永远先跑、不被 waiter 拦。
  2. waiter 检查:若有挂起 waiter 命中本事件且其 block 为真,吞掉事件、不再下传。
  3. default handler:按优先级(小者先)逐个跑。

每个命令 / 事件型 handler 内部依次过:事件种类预筛(#[event])→ 启用门 ([EnabledSet])→ 匹配器([Matcher],命中产出 ParsedCommand)→ 门控 [Rule](权限 / 场景 / 冷却)→ handler 调用。任一步不过即跳过本 handler,同层 handler 互不阻断。门控否决时可经 reply-on-veto 通道回贴一句(如休眠的「Zzz」)。

交互模型:Waiter / Session

处理一个事件时,handler 可从 [Ctx] 提取一个 [Session],再 .waiter() 挂起一个 [Waiter]:它把后续命中事件经 mpsc 投递回来(多轮、可嵌套,深者优先),handler 借此实现「追问 → 等回答」的多步对话,无需为每步注册全局 handler。需要跨两个独立 事件(可能相距很远、在不同会话)的流程则用 [Rendezvous]。