把 AssistantEvent 列表组装成一条完整的 AI 消息。 逻辑: 1. 累积 text_delta → 合并成一个 TextBlock 2. 遇到 tool_use → 先把之前累积的文本存起来,再存工具调用 3. 记录 usage 4. 检查是否收到 message_stop 对应源码: conversation.rs:353-390 (build_assistant_message)
(events: list[AssistantEvent])
| 544 | |
| 545 | |
| 546 | def build_assistant_message(events: list[AssistantEvent]) -> AssistantMessage: |
| 547 | """ |
| 548 | 把 AssistantEvent 列表组装成一条完整的 AI 消息。 |
| 549 | |
| 550 | 逻辑: |
| 551 | 1. 累积 text_delta → 合并成一个 TextBlock |
| 552 | 2. 遇到 tool_use → 先把之前累积的文本存起来,再存工具调用 |
| 553 | 3. 记录 usage |
| 554 | 4. 检查是否收到 message_stop |
| 555 | |
| 556 | 对应源码: conversation.rs:353-390 (build_assistant_message) |
| 557 | """ |
| 558 | blocks = [] |
| 559 | current_text = "" # 正在累积的文本 |
| 560 | input_tokens = 0 |
| 561 | output_tokens = 0 |
| 562 | finished = False |
| 563 | |
| 564 | for event in events: |
| 565 | if event.event_type == AssistantEventType.TEXT_DELTA: |
| 566 | current_text += event.text |
| 567 | |
| 568 | elif event.event_type == AssistantEventType.TOOL_USE: |
| 569 | # 遇到工具调用 → 先把之前的文本存起来 |
| 570 | if current_text: |
| 571 | blocks.append(ContentBlock(block_type="text", text=current_text)) |
| 572 | current_text = "" |
| 573 | # 再存工具调用 |
| 574 | blocks.append(ContentBlock( |
| 575 | block_type="tool_use", |
| 576 | tool_id=event.tool_id, |
| 577 | tool_name=event.tool_name, |
| 578 | tool_input=event.tool_input, |
| 579 | )) |
| 580 | |
| 581 | elif event.event_type == AssistantEventType.USAGE: |
| 582 | input_tokens = event.input_tokens |
| 583 | output_tokens = event.output_tokens |
| 584 | |
| 585 | elif event.event_type == AssistantEventType.MESSAGE_STOP: |
| 586 | finished = True |
| 587 | |
| 588 | # 把最后累积的文本也存起来 |
| 589 | if current_text: |
| 590 | blocks.append(ContentBlock(block_type="text", text=current_text)) |
| 591 | |
| 592 | if not finished: |
| 593 | print(" [WARNING] 流结束了但没收到 message_stop 事件!") |
| 594 | |
| 595 | return AssistantMessage( |
| 596 | blocks=blocks, |
| 597 | input_tokens=input_tokens, |
| 598 | output_tokens=output_tokens, |
| 599 | ) |
| 600 | |
| 601 | |
| 602 | # ============================================================ |
no test coverage detected