Files
social-app/docs/plans/2026-03-12-agent-ui-schema-events-implementation-plan.md
T
zl-q 7b8865e256 feat: 添加 Agent 步骤事件与图片附件功能
- 新增 stepStarted/stepFinished 事件类型支持
- 前端实现图片附件上传和预览功能
- 后端增强工具结果存储和事件处理
- 完善相关单元测试和集成测试
2026-03-12 09:29:57 +08:00

9.8 KiB

Agent UI Schema and Event Wiring Implementation Plan

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: 打通 agent 工具结果在实时事件与历史回放的一致渲染链路:SSE 实时带 UI,落库 content 存摘要,完整 UI schema 存 storage 并通过 metadata 回填。

Architecture: 后端在 TOOL_CALL_RESULT 持久化链路中引入“摘要 + 全量分离”策略:摘要写 messages.content,全量 payload 写对象存储,metadata 仅存索引路径;history 读取时按 metadata 反查 storage 回填 ui。前端复用现有 AG-UI 事件模型,实现 runs/events/history 三路统一映射到 ChatListItem,并补齐 step 事件渲染与 history 多模态渲染。

Tech Stack: FastAPI, SQLAlchemy, AgentScope runtime/events, Supabase Storage, Flutter (Bloc/Cubit), Dart models/tests, AG-UI events


Task 1: Add Tool Summary Rule Engine (Backend)

Files:

  • Create: backend/src/core/agentscope/events/tool_result_summary.py
  • Test: backend/tests/unit/core/agentscope/events/test_tool_result_summary.py

Step 1: Write the failing test

from core.agentscope.events.tool_result_summary import build_tool_content_summary


def test_calendar_write_summary() -> None:
    text = build_tool_content_summary(
        tool_name="calendar_write",
        args={"title": "项目评审"},
        result={"start_time": "明天 10:00"},
        error=None,
    )
    assert text.startswith("已创建日程")

Step 2: Run test to verify it fails

Run: uv run pytest backend/tests/unit/core/agentscope/events/test_tool_result_summary.py -q Expected: FAIL with import/module/function missing.

Step 3: Write minimal implementation

def build_tool_content_summary(*, tool_name: str, args, result, error) -> str:
    if error:
        return f"{tool_name} 执行失败"
    if tool_name == "calendar_write":
        return "已创建日程"
    return f"{tool_name} 执行完成"

Step 4: Run test to verify it passes

Run: uv run pytest backend/tests/unit/core/agentscope/events/test_tool_result_summary.py -q Expected: PASS.

Step 5: Extend tests for all rules and refactor

Add cases for calendar_read/calendar_delete/calendar_share/user_resolve/error/fallback/truncation and implement full rule table.

Step 6: Commit

git add backend/src/core/agentscope/events/tool_result_summary.py backend/tests/unit/core/agentscope/events/test_tool_result_summary.py
git commit -m "feat: add deterministic tool result summary engine"

Task 2: Persist Full Tool Payload to Storage and Keep Content Lightweight

Files:

  • Modify: backend/src/core/agentscope/events/store.py
  • Test: backend/tests/unit/core/agentscope/events/test_store.py

Step 1: Write the failing tests

Add tests asserting:

  • TOOL_CALL_RESULT persists summary to content.
  • metadata includes storage_bucket/storage_path/tool_call_id.
  • uploaded payload includes full ui/args/result/error.

Step 2: Run targeted tests (RED)

Run: uv run pytest backend/tests/unit/core/agentscope/events/test_store.py -q Expected: FAIL on new assertions.

Step 3: Implement minimal storage write path

In _persist_tool_call_result:

  • build full_payload from event fields.
  • call summary engine for content.
  • upload payload via tool result storage (inject dependency if needed).
  • store only path/index in metadata.

Step 4: Run tests (GREEN)

Run: uv run pytest backend/tests/unit/core/agentscope/events/test_store.py -q Expected: PASS.

Step 5: Add fallback test and implementation

Add case where storage upload fails but tool message still persists with summary and no crash.

Step 6: Commit

git add backend/src/core/agentscope/events/store.py backend/tests/unit/core/agentscope/events/test_store.py
git commit -m "feat: store tool payload in object storage with metadata index"

Task 3: Hydrate History Tool UI from Metadata Storage Path

Files:

  • Modify: backend/src/v1/agent/repository.py
  • Test: backend/tests/unit/v1/agent/test_repository.py

Step 1: Write failing tests

Add/adjust assertions:

  • history tool payload resolves ui from storage payload.
  • when storage missing, fallback to messages.content summary.

Step 2: Run tests (RED)

Run: uv run pytest backend/tests/unit/v1/agent/test_repository.py -q Expected: FAIL on ui hydration and fallback assertions.

Step 3: Implement minimal hydration logic

In _to_snapshot_message for tool role:

  • read storage via metadata.storage_bucket/storage_path.
  • map hydrated payload fields to snapshot (ui, content, toolCallId).
  • keep safe fallback when storage read fails.

Step 4: Run tests (GREEN)

Run: uv run pytest backend/tests/unit/v1/agent/test_repository.py -q Expected: PASS.

Step 5: Commit

git add backend/src/v1/agent/repository.py backend/tests/unit/v1/agent/test_repository.py
git commit -m "fix: hydrate tool ui from metadata storage in history snapshots"

Task 4: Keep SSE TOOL_CALL_RESULT Compatible with Existing Frontend Parsing

Files:

  • Modify: backend/src/core/agentscope/runtime/agent_route_runtime.py
  • Test: backend/tests/unit/core/agentscope/runtime/test_agent_route_runtime.py

Step 1: Write failing test

Add assertion that emitted TOOL_CALL_RESULT data contains expected renderable fields (callId/toolName/result/error and ui path from result payload).

Step 2: Run tests (RED)

Run: uv run pytest backend/tests/unit/core/agentscope/runtime/test_agent_route_runtime.py -q Expected: FAIL on missing/incorrect payload fields.

Step 3: Implement minimal payload normalization

Normalize tool result event payload so frontend can keep current parsing without contract breaks.

Step 4: Run tests (GREEN)

Run: uv run pytest backend/tests/unit/core/agentscope/runtime/test_agent_route_runtime.py -q Expected: PASS.

Step 5: Commit

git add backend/src/core/agentscope/runtime/agent_route_runtime.py backend/tests/unit/core/agentscope/runtime/test_agent_route_runtime.py
git commit -m "fix: preserve frontend-compatible tool result event payload"

Task 5: Wire Frontend History + Events to Unified Rendering Path

Files:

  • Modify: apps/lib/features/chat/data/services/ag_ui_service.dart
  • Modify: apps/lib/features/chat/presentation/bloc/chat_bloc.dart
  • Modify: apps/lib/features/chat/data/models/tool_result.dart
  • Modify: apps/lib/features/home/ui/screens/home_screen.dart
  • Test: apps/test/features/chat/ag_ui_service_test.dart
  • Create/Modify: apps/test/features/chat/chat_bloc_test.dart

Step 1: Write failing tests

Add tests asserting:

  • history tool message with ui becomes ToolResultItem.
  • SSE TOOL_CALL_RESULT with ui renders same item shape.
  • attachments in history user message are mapped for multimodal rendering.

Step 2: Run tests (RED)

Run: cd apps && flutter test test/features/chat/ag_ui_service_test.dart Expected: FAIL on new mapping assertions.

Step 3: Implement minimal mapping changes

  • In service/bloc, unify history and event mapping into same conversion path.
  • Keep existing UiSchemaRenderer input format untouched.
  • Ensure fallback to content text when ui missing.

Step 4: Run tests (GREEN)

Run: cd apps && flutter test test/features/chat/ag_ui_service_test.dart Expected: PASS.

Step 5: Commit

git add apps/lib/features/chat/data/services/ag_ui_service.dart apps/lib/features/chat/presentation/bloc/chat_bloc.dart apps/lib/features/chat/data/models/tool_result.dart apps/lib/features/home/ui/screens/home_screen.dart apps/test/features/chat/ag_ui_service_test.dart apps/test/features/chat/chat_bloc_test.dart
git commit -m "feat: unify realtime and history tool card rendering"

Task 6: Add Step Event Rendering for Intent/Execution/Report

Files:

  • Modify: apps/lib/features/chat/presentation/bloc/chat_bloc.dart
  • Modify: apps/lib/features/home/ui/screens/home_screen.dart
  • Test: apps/test/features/chat/chat_bloc_test.dart

Step 1: Write failing test

Add test verifying STEP_STARTED/STEP_FINISHED transitions produce visible stage state.

Step 2: Run tests (RED)

Run: cd apps && flutter test test/features/chat/chat_bloc_test.dart Expected: FAIL on missing stage state.

Step 3: Implement minimal state and UI

  • Track current stage enum in ChatState.
  • Render compact stage progress row in chat screen.

Step 4: Run tests (GREEN)

Run: cd apps && flutter test test/features/chat/chat_bloc_test.dart Expected: PASS.

Step 5: Commit

git add apps/lib/features/chat/presentation/bloc/chat_bloc.dart apps/lib/features/home/ui/screens/home_screen.dart apps/test/features/chat/chat_bloc_test.dart
git commit -m "feat: render agent step progress from AG-UI events"

Task 7: Verification Gate (Backend + Frontend)

Files:

  • Modify (if needed): docs/plans/2026-03-11-agent-multimodal-smoke-runbook.md

Step 1: Run backend targeted tests

Run: uv run pytest backend/tests/unit/core/agentscope/events/test_tool_result_summary.py backend/tests/unit/core/agentscope/events/test_store.py backend/tests/unit/v1/agent/test_repository.py backend/tests/unit/core/agentscope/runtime/test_agent_route_runtime.py -q Expected: PASS.

Step 2: Run frontend targeted tests

Run: cd apps && flutter test test/features/chat/ag_ui_service_test.dart test/features/chat/chat_bloc_test.dart Expected: PASS.

Step 3: Run backend quality checks

Run: uv run ruff check backend/src backend/tests Expected: PASS.

Step 4: Run backend type checks

Run: uv run basedpyright Expected: 0 errors.

Step 5: Update runbook evidence

Record changed contract, test evidence, and known follow-ups.

Step 6: Commit

git add docs/plans/2026-03-11-agent-multimodal-smoke-runbook.md
git commit -m "docs: record tool ui schema storage and rendering verification"