A6 · 事件体系与扩展点分类(会话 / Agent / 能力事件)
developer preview:API 可能变更。
1. 三域事件模型
dsh 扩展点是事件,选对**事件域(domain)**是大多数改动的第一步:
- 会话事件(Session Events) :追加到日志、通过
session/event广播的持久事实。当某事实必须在 reload 后仍然存在时用它。 - Agent 事件(
agent/*) :携带活跃Agent(inbox / step / status / request / validation / continuation)。要观察或拦截「进行中的工作」时用它。 - 能力事件(Capability Events) :无需导入循环即可向某个 seam(
fs/*、tools/*、telemetry/*)附加策略与适配器。
2. 扩展点选择决策
#mermaid-svg-MnLNPILk2S5D17QM{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-MnLNPILk2S5D17QM .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-MnLNPILk2S5D17QM .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-MnLNPILk2S5D17QM .error-icon{fill:#552222;}#mermaid-svg-MnLNPILk2S5D17QM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-MnLNPILk2S5D17QM .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-MnLNPILk2S5D17QM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-MnLNPILk2S5D17QM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-MnLNPILk2S5D17QM .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-MnLNPILk2S5D17QM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-MnLNPILk2S5D17QM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-MnLNPILk2S5D17QM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-MnLNPILk2S5D17QM .marker.cross{stroke:#333333;}#mermaid-svg-MnLNPILk2S5D17QM svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-MnLNPILk2S5D17QM p{margin:0;}#mermaid-svg-MnLNPILk2S5D17QM .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-MnLNPILk2S5D17QM .cluster-label text{fill:#333;}#mermaid-svg-MnLNPILk2S5D17QM .cluster-label span{color:#333;}#mermaid-svg-MnLNPILk2S5D17QM .cluster-label span p{background-color:transparent;}#mermaid-svg-MnLNPILk2S5D17QM .label text,#mermaid-svg-MnLNPILk2S5D17QM span{fill:#333;color:#333;}#mermaid-svg-MnLNPILk2S5D17QM .node rect,#mermaid-svg-MnLNPILk2S5D17QM .node circle,#mermaid-svg-MnLNPILk2S5D17QM .node ellipse,#mermaid-svg-MnLNPILk2S5D17QM .node polygon,#mermaid-svg-MnLNPILk2S5D17QM .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-MnLNPILk2S5D17QM .rough-node .label text,#mermaid-svg-MnLNPILk2S5D17QM .node .label text,#mermaid-svg-MnLNPILk2S5D17QM .image-shape .label,#mermaid-svg-MnLNPILk2S5D17QM .icon-shape .label{text-anchor:middle;}#mermaid-svg-MnLNPILk2S5D17QM .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-MnLNPILk2S5D17QM .rough-node .label,#mermaid-svg-MnLNPILk2S5D17QM .node .label,#mermaid-svg-MnLNPILk2S5D17QM .image-shape .label,#mermaid-svg-MnLNPILk2S5D17QM .icon-shape .label{text-align:center;}#mermaid-svg-MnLNPILk2S5D17QM .node.clickable{cursor:pointer;}#mermaid-svg-MnLNPILk2S5D17QM .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-MnLNPILk2S5D17QM .arrowheadPath{fill:#333333;}#mermaid-svg-MnLNPILk2S5D17QM .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-MnLNPILk2S5D17QM .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-MnLNPILk2S5D17QM .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MnLNPILk2S5D17QM .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-MnLNPILk2S5D17QM .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MnLNPILk2S5D17QM .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-MnLNPILk2S5D17QM .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-MnLNPILk2S5D17QM .cluster text{fill:#333;}#mermaid-svg-MnLNPILk2S5D17QM .cluster span{color:#333;}#mermaid-svg-MnLNPILk2S5D17QM div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-MnLNPILk2S5D17QM .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-MnLNPILk2S5D17QM rect.text{fill:none;stroke-width:0;}#mermaid-svg-MnLNPILk2S5D17QM .icon-shape,#mermaid-svg-MnLNPILk2S5D17QM .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MnLNPILk2S5D17QM .icon-shape p,#mermaid-svg-MnLNPILk2S5D17QM .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-MnLNPILk2S5D17QM .icon-shape .label rect,#mermaid-svg-MnLNPILk2S5D17QM .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MnLNPILk2S5D17QM .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-MnLNPILk2S5D17QM .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-MnLNPILk2S5D17QM :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 要扩展什么?
持久事实 / 跨 reload
拦截进行中的工作
给 seam 加策略/适配器
监听 session/* 事件
监听 agent/* 事件
监听 fs/* / tools/* / telemetry/*
3. 真实事件名清单(来自源码声明)
ts
// packages/core/session/src/index.ts
'session/created' // emit
'session/event' // emit ------ 渲染 UI 的主事件流
'session/flush' // emit
// packages/core/agent/src/runtime-types.ts
'agent/pre-step'(...): Promise<PreStepDecision> // waterfall
'agent/request'(...): Promise<LlmCallConfig> // waterfall
'agent/request-error'(...): RequestErrorAction // waterfall
'agent/turn-stopping'(...): void // serial(无 next)
'agent/status' // emit
// packages/core/tools/src/index.ts
'tools/pre-execute'(exec, next): Promise<PreToolDecision> // waterfall
'tools/execute'(exec, next): Promise<ToolExecutionResult> // waterfall
'tools/post-execute'(exec, result, next) // waterfall
'tools/result'(exec, result) // emit
4. 可运行示例:从 session/event 渲染助手文本
ts
import type { Context } from '@deepseek-ai/cordis'
import { SessionId } from '@deepseek-ai/dsh-session'
export const name = 'ui-echo'
export const inject = ['agents']
export function apply(ctx: Context) {
ctx.on('session/event', (_session, event) => {
if (event.type === 'assistant/chunk' && event.data.chunk.type === 'text-delta') {
process.stdout.write(event.data.chunk.text)
}
})
}
5. 核心术语中英对照
| 中文 | 英文 | 说明 |
|---|---|---|
| 会话事件 | Session Event | 持久、入日志 |
| Agent 事件 | Agent Event | 实时拦截 agent/* |
| 能力事件 | Capability Event | fs/* / tools/* / telemetry/* |
| 生产者 / 消费者 | Producer / Consumer | 事件的发出与接收方 |
6. 官方文档 vs 源码 对照表
| 主题 | 官方文档 | 精确源码路径 |
|---|---|---|
| 事件总览 | reference/#事件 |
docs/architecture.md |
| 事件生产者 / 消费者矩阵 | reference/event-producer-consumer |
docs/event-producer-consumer.md(自动生成) |
| session 事件 | reference/subsystems/session |
packages/core/session/src/index.ts |
| agent 事件 | reference/subsystems/core |
packages/core/agent/src/runtime-types.ts |
| tools 事件 | reference/subsystems/tools |
packages/core/tools/src/index.ts |
7. 一句话小结
dsh 把「可扩展点」做成三类事件域:要持久就落 session 日志,要拦截就挂 agent/*,要给能力加策略就监听对应 seam 的 * 事件------扩展前先选对域。