feat: agent 实时输出流(SSE)

B-② SSE 实时流(⑧ ★ GET /api/tasks/:id/stream):

后端:
- GET /api/tasks/:id/stream:SSE 跟随任务最近一条 run 的 transcript 文件,
  新写入的 agent 消息逐行推送(活跃 run=实时;已结束=回放后 end);
  500ms 轮询 tail(按 offset 增量读),run 转非 started 即结束流,客户端断开即停

前端:
- StreamModal(EventSource 消费 SSE,summarizeMessage 把 SDK 消息→可读行:
  助手文本/⚙工具调用/■终态/·maestro 元事件,自动滚动到底)
- AgentSection agent 行可点击 → 打开实时流模态;adaptActiveAgents 带出 taskId

验证:typecheck 干净;前端 build 通过;dev 渲染 0 console 错误。
(实时效果需有运行中的 agent;端到端随 daemon 重启验证。)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-24 17:01:58 +08:00
parent 9b17d3e24f
commit a688b6977e
4 changed files with 105 additions and 5 deletions
+1 -1
View File
@@ -160,7 +160,7 @@ export function adaptActiveAgents(agentsResp, projectId) {
if (projectId && a.projectId !== projectId) continue;
for (const r of a.active || []) {
out.push({
id: r.runId || r.id, project: a.projectName,
id: r.runId || r.id, taskId: r.taskId, project: a.projectName,
title: r.title || r.taskTitle || r.taskId || '(运行中)',
kind: (r.kind || 'run').toUpperCase(),
time: TIME(r.startedAt || r.at), meta: `${r.worktree || ''} · ${r.model || ''}`,