Files
kwcode/kaiwu/core/event_bus.py
Val-sss d5ce4342f6 v1.5.0: SearchSubagent isolated search + UpstreamManifest cross-file contracts
Architecture upgrade to improve task completion for any model size:
- SearchSubagent: independent context window, parallel file reads, clean results only
- UpstreamManifest: deterministic AST extraction of signatures/constants, zero LLM
- PENCIL-style compression: subtask results compacted to structured artifacts
- Verifier pre-check: cross-file contract consistency before running tests
- Generator context slimmed: upstream_constraints + retry_hint injection

Code quality:
- orchestrator.py run() split into 5 private methods (410->253 lines)
- Full type annotations (Optional[DebugSubagent], Callable types)
- __all__ added to 7 core modules
- pyproject.toml: license fixed, ruff + mypy configured
- TUI: 30+ event icons, Server: /api/manifest endpoint
- STATUS.md rewritten: concise, English, professional format

451/451 tests green, 27 new tests for SearchSubagent+Manifest.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-06 17:08:08 +08:00

79 lines
2.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
EventBus: 统一事件总线Event Sourcing 模式)。
append-only 日志支持 replay/调试,替代分散的 on_status 回调。
理论来源:
- Event SourcingMartin Fowler
- CC 27 个 hook 事件arXiv:2604.14228
- Codified Context append-only 日志arXiv:2602.20478
"""
from collections import defaultdict
from typing import Callable
import time
import logging
logger = logging.getLogger(__name__)
__all__ = ["EventBus"]
class EventBus:
"""
统一事件总线。
- on(event, handler) 注册监听
- emit(event, payload) 发射事件
- replay() 返回完整事件日志
"""
def __init__(self):
self._handlers: dict[str, list[Callable]] = defaultdict(list)
self._wildcard: list[Callable] = []
self._log: list[dict] = []
def on(self, event: str, handler: Callable):
"""注册事件处理器。event="*" 监听所有事件。"""
if event == "*":
self._wildcard.append(handler)
else:
self._handlers[event].append(handler)
def off(self, event: str, handler: Callable):
"""移除事件处理器。"""
if event == "*":
try:
self._wildcard.remove(handler)
except ValueError:
pass
else:
try:
self._handlers[event].remove(handler)
except ValueError:
pass
def emit(self, event: str, payload: dict | None = None):
"""发射事件,通知所有监听器,同时记录到日志。"""
payload = payload or {}
entry = {"t": time.time(), "event": event, **payload}
self._log.append(entry)
for h in self._handlers.get(event, []) + self._wildcard:
try:
h(event, payload)
except Exception as e:
logger.debug("EventBus handler error [%s]: %s", event, e)
def replay(self) -> list[dict]:
"""返回完整事件日志副本。"""
return list(self._log)
def clear_log(self):
"""清空事件日志不影响已注册的handler"""
self._log.clear()
def handler_count(self) -> int:
"""返回已注册handler总数。"""
total = len(self._wildcard)
for handlers in self._handlers.values():
total += len(handlers)
return total