两种协议的流式记录（虚构服务，教学用，全部虚构）
组织方式差异是本文件要突出的重点：一边的结束是事件，另一边的结束是哨兵字符串。

##################### A 段 · Messages API：每帧是 event: 加 data: 两行 #####################

event: message_start
data: {"type":"message_start","message":{"id":"msg_demo_002","role":"assistant","model":"example-chat-mini"}}

event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}

event: ping
data: {"type":"ping"}

event: content_block_delta
data: {"type":"content_block_delta","delta":{"type":"text_delta","text":"你"}}

event: content_block_delta
data: {"type":"content_block_delta","delta":{"type":"text_delta","text":"好，材料里有日期与名额。"}}

event: content_block_stop
data: {"type":"content_block_stop","index":0}

event: content_block_start
data: {"type":"content_block_start","index":1,"content_block":{"type":"tool_use","id":"toolu_demo_77","name":"record_activity","input":{}}}

event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"{\"activity_name\":"}}

event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" \"旧书修复工作坊（第 4 期）\"}"}}

event: content_block_stop
data: {"type":"content_block_stop","index":1}

event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"tool_use"},"usage":{"output_tokens":96}}

event: message_stop
data: {"type":"message_stop"}


##################### B 段 · Chat Completions：通常只有 data: 行 #####################

data: {"choices":[{"index":0,"delta":{"role":"assistant","content":""}}]}

data: {"choices":[{"index":0,"delta":{"content":"你"}}]}

data: {"choices":[{"index":0,"delta":{"content":"好，材料里有日期与名额。"}}]}

data: {"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_demo_118","type":"function","function":{"name":"record_activity","arguments":"{\"activity_name\": "}}]}}]}

data: {"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"旧书修复工作坊（第 4 期）\"}"}}]}}]}

data: {"choices":[{"index":0,"delta":{},"finish_reason":"tool_calls"}],"usage":null}

data: [DONE]


##################### C 段 · 两段被截断的记录 #####################

C-1（来自 A 段那类服务，缺最后一个事件）：

event: message_start
data: {"type":"message_start","message":{"id":"msg_demo_003","role":"assistant"}}

event: content_block_delta
data: {"type":"content_block_delta","delta":{"type":"text_delta","text":"报名截止日期是"}}

（连接在此中断：没有 content_block_stop，没有 message_delta，没有 message_stop）

C-2（来自 B 段那类服务，缺哨兵行）：

data: {"choices":[{"index":0,"delta":{"content":"报名截止日期是"}}]}

（连接在此中断：没有带 finish_reason 的帧，也没有 data: [DONE]）


##################### D 段 · 一次「逐行转发」实验 #####################

转换脚本把 A 段的每一行原样搬到 B 段客户端，只删掉 `event:` 行、保留 `data:` 行。
观察到的现象（记录，不解释）：

1. B 段客户端读到的第一行 data 是 {"type":"message_start",...}，它没有 choices 字段。
2. 文本增量出现在 delta.text_delta 位置，而 B 段客户端在找 choices[0].delta.content。
3. 工具参数在 A 段是 input_json_delta 的若干片，B 段客户端在等 tool_calls 数组。
4. A 段的结束是一行 event: message_stop，B 段客户端一直等 data: [DONE]。
5. 半截的工具参数字符串被当成正文显示了出来。

需要你自己回答：哪些项必须靠「按事件类型分发」才能对上，哪些项根本对不上、只能显式声明不支持。
