跳转至

三大事件域深度解析

"Events are the extension points." —— 事件就是 DSH 的扩展点。

在许多传统框架中,事件系统通常是一个简单的全局 EventEmitter。而 DSH 构建了一个分层明确的 三大事件域体系,从根本上杜绝了事件混乱和状态污染。


核心文件速查

路径 职责 重要度
packages/core/session/src/types.ts 会话事件(SessionEvent)类型全集 ⭐⭐⭐
packages/core/agent/src/dispatch.ts Waterfall 与 Serial Agent 事件派发器 ⭐⭐⭐
docs/event-producer-consumer.zh.md 全系统事件生产者与消费者矩阵 ⭐⭐⭐

三大事件域全景剖析

┌─────────────────────────────────────────────────────────────────────────────┐
│ 1. Session Events (会话事件域 - 持久化事实)                                    │
│    特点: 纯追加日志、可持久化、重启后严格重放、"模型可见即已记录"                 │
│    事件: turn/start, step/start, user/message, assistant/chunk, tool/call...│
└──────────────────────────────────────┬──────────────────────────────────────┘
                                       │
┌──────────────────────────────────────▼──────────────────────────────────────┐
│ 2. Agent Events (智能体事件域 - 实时控制流拦截)                                │
│    特点: Waterfall / Serial 管道,支持 next() 委托、动态改写与拦截           │
│    事件: agent/pre-step, agent/request, agent/turn-stopping, agent/idle     │
└──────────────────────────────────────┬──────────────────────────────────────┘
                                       │
┌──────────────────────────────────────▼──────────────────────────────────────┐
│ 3. Capability Events (能力事件域 - 平台功能挂载)                              │
│    特点: 针对具体能力的解耦适配点,无循环导入                                │
│    事件: tools/pre-execute, tools/execute, fs/write, llm/stream, telemetry/* │
└─────────────────────────────────────────────────────────────────────────────┘

1. 会话事件域(Session Events):可重放的不可变事实

会话事件代表系统中已经发生的客观事实。 所有会话事件均实现 SessionEvent 接口,并写入追加日志:

export type SessionEvent =
  | { type: 'turn/start'; turnId: string; timestamp: number }
  | { type: 'turn/end'; turnId: string; timestamp: number }
  | { type: 'step/start'; stepId: string; timestamp: number }
  | { type: 'step/end'; stepId: string; timestamp: number }
  | { type: 'user/message'; messageId: string; content: ContentBlock[] }
  | { type: 'assistant/chunk'; chunkId: string; delta: string }
  | { type: 'assistant/message'; messageId: string; content: ContentBlock[] }
  | { type: 'tool/call'; callId: string; name: string; args: JsonValue }
  | { type: 'tool/result'; callId: string; result: JsonValue; error?: boolean }
  • 不可篡改性:已落盘的事件永不修改;
  • 回放保真度:前端重新打开页面时,通过拉取 SessionEvent 历史,可以直接以逐字逐块的保真度回放 Agent 的思考与打字过程。

2. Agent 事件域(Agent Events):Waterfall 拦截流

Agent 事件用于在工作进行中对其进行观察或拦截。 其中最强大的设计是 Waterfall(瀑布流事件)

在 Waterfall 监听器中,每个处理器必须调用 next() 才能将控制权传递给下一个插件,或者返回修改后的数据:

// 示例:注入安全合规检查的 Waterfall 监听器
ctx.on('agent/pre-step', async (event, next) => {
  // 1. 检查输入是否包含违规敏感词
  if (containsSensitiveKeyword(event.inputs)) {
    return { status: 'reject', reason: 'Policy violation' }
  }

  // 2. 动态改写用户输入(例如追加特定的系统上下文指令)
  const enrichedInputs = enrichWithProjectContext(event.inputs)

  // 3. 传递给下一个插件
  return next({ ...event, inputs: enrichedInputs })
})

3. 能力事件域(Capability Events):无侵入适配

能力事件允许我们在不修改底层库源码的前提下,向特定的系统操作注入切面逻辑。

例如在文件操作时: - fs/before-write:可以在写入文件前自动创建备份副本; - tools/pre-execute:可以在工具执行前校验沙箱权限与用户交互审批; - telemetry/span:收集分布式追踪与 Token 消耗指标。


本章思考与自测

  1. 思考题:为什么 turn/start 是一个 Session Event,而 agent/pre-step 却是一个 Agent Event?它们的核心区别是什么?
  2. 自测题:如果在 Waterfall 事件链中,某个插件没有调用 next() 也没有返回值,会发生什么?DSH 是如何防止插件挂起整个 Agent 循环的?