"""Kernel 事件日志:一炁(EventStore)之上的 Kernel 写入接口。 - 落库走 ``DbEventStore``(run 内单调 sequence,DB 为事实源,SSE 断线重放依据); - 双发进程内 ``bus``(RunEventBus)供既有 ``/runs/{id}/stream`` SSE 实时转发。 该双发是 M0 骨架的过渡接法,M2 重建 runs 路由时收敛为 EventStore 单通道。 """ from __future__ import annotations from typing import Any from app.modules.runtime.events import Event, EventStore from app.schemas.runtime import EventResponse from app.services.event_bus import bus class KernelEventLog: """Kernel 视角的事件写入与检索。""" def __init__(self, store: EventStore) -> None: self._store = store async def emit( self, *, type: str, # noqa: A002 — 对齐事件字段名 run_id: str, character_id: str, source: str = "kernel", payload: dict[str, Any] | None = None, visibility: str = "public", trace_id: str | None = None, ) -> Event: event = await self._store.append( Event( type=type, source=source, payload=payload or {}, visibility=visibility, # type: ignore[arg-type] run_id=run_id, character_id=character_id, trace_id=trace_id, ) ) bus.publish(run_id, _to_response(event)) return event async def list_by_run(self, run_id: str) -> list[Event]: return await self._store.list_by_run(run_id) def _to_response(event: Event) -> EventResponse: return EventResponse( event_id=event.id, run_id=event.run_id or "", character_id=event.character_id or "", type=event.type, sequence=event.sequence if event.sequence is not None else 0, visibility=event.visibility, payload=event.payload, created_at=event.created_at, trace_id=event.trace_id, )