From 7fae280b014eaa7691f21a0fbb865a8b73328470 Mon Sep 17 00:00:00 2001 From: wonder Date: Wed, 29 Apr 2026 20:17:22 +0800 Subject: [PATCH] vault backup: 2026-04-29 20:17:22 --- ...ter_02_chatmodelagent_runner_agentevent.md | 4 + .../async_iterator_consumption.md | 94 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 Eino/quick_start/chapter_02_chatmodelagent_runner_agentevent/async_iterator_consumption.md diff --git a/Eino/quick_start/chapter_02_chatmodelagent_runner_agentevent.md b/Eino/quick_start/chapter_02_chatmodelagent_runner_agentevent.md index 5f489ee..855553b 100644 --- a/Eino/quick_start/chapter_02_chatmodelagent_runner_agentevent.md +++ b/Eino/quick_start/chapter_02_chatmodelagent_runner_agentevent.md @@ -324,6 +324,10 @@ for { > - **不要忽略 `event.Err`**——Agent 内部可能静默失败(如工具执行超时) > - **注意 goroutine 安全**——多个消费者同时读取同一个 AsyncIterator 是不安全的 +> [!question] 深入理解事件流消费模式? +> 通过 Claude Code Agent 事件流消费的类比加深理解。 +> -> 参考 [[chapter_02_chatmodelagent_runner_agentevent/async_iterator_consumption|AsyncIterator:事件流的消费方式]] + ## 多轮对话的实现 本章实现的是简单的多轮对话:用户输入 → 模型回复 → 用户继续输入 → ... diff --git a/Eino/quick_start/chapter_02_chatmodelagent_runner_agentevent/async_iterator_consumption.md b/Eino/quick_start/chapter_02_chatmodelagent_runner_agentevent/async_iterator_consumption.md new file mode 100644 index 0000000..26a898c --- /dev/null +++ b/Eino/quick_start/chapter_02_chatmodelagent_runner_agentevent/async_iterator_consumption.md @@ -0,0 +1,94 @@ +--- +tags: [eino, asynciterator, go, streaming] +create time: 2026-04-29 15:30 +--- + +# AsyncIterator:事件流的消费方式 + +## 概述 + +理解 Eino 的 `AsyncIterator` 最简单的方式——**看 Claude Code 是怎么消费自身事件的**。两者的消费过程完全一致。 + +--- + +## Claude Code 的事件消费过程 + +```mermaid +flowchart TD + A["runner.Run() 获取事件流"] --> B["循环 events.Next()"] + B --> C{"事件类型?"} + C -->|"thinking"| D["显示思考过程"] + C -->|"text_delta"| E["追加文本到终端"] + C -->|"tool_use"| F["高亮工具调用"] + C -->|"error"| G["记录错误,终止"] + C -->|"interrupt"| H["用户取消,优雅退出"] + C -->|"无更多事件"| I["closeConnection()"] + + D --> B + E --> B + F --> B + style A fill:#e1f5fe + style I fill:#ffebee +``` + +核心过程只有一句:**获取流 → Next() 逐个拉取 → 按类型处理 → Close 释放。** + +--- + +## Eino 的等价过程 + +```mermaid +flowchart TD + A["runner.Run() 获取迭代器"] --> B["循环 events.Next()"] + B --> C{"event.Err?"} + C -->|是| G["记录错误,退出循环"] + C -->|否| D{"event.Output?"} + D -->|是| E["打印内容给用户"] + D -->|否| F{"event.Action?"} + F -->|是| J["处理控制动作
本章节用不到"] + F -->|否| B + E --> B + G --> H["events.Close() 释放资源"] + + style A fill:#e1f5fe + style H fill:#ffebee +``` + +同样四个字阶段:获取流 → Next() 逐个拉取 → 按类型处理 → Close 释放。 + +--- + +## 两者对照 + +```mermaid +flowchart LR + subgraph Claude Code + A["thinking"] --> T1["显示思考过程"] + B["text_delta"] --> T2["追加文本输出"] + C["tool_use"] --> T3["高亮工具调用"] + D["error"] --> T4["错误终止"] + E["interrupt"] --> T5["用户取消"] + end + + subgraph Eino ADK + A1["—"] --> S1["无此概念"] + B1["event.Output"] --> S2["打印消息内容"] + C1["event.Action"] --> S3["内部调度信号"] + D1["event.Err"] --> S4["错误退出"] + E1["ctx 被 cancel"] --> S5["用户取消"] + end + + B -.等价.-> B1 + C -.等价.-> C1 + D -.等价.-> D1 + E -.等价.-> E1 +``` + +--- + +## 注意事项 + +- 始终检查 `Err` 字段——错误通常是静默发生的 +- `Next()` 返回的 `ok` 为 false 时表示流已结束,不应继续调用 +- 每次 `Run()` 创建的迭代器只能消费一次,不能复用 +- 不手动调用 `Close()` 会导致资源泄漏