boardx / boardx/workspacex

实时消息流里失败的工具调用仍显示绿色对勾——#3204 ① 只收敛了轨迹面板那一半

Open
#3,257 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
0
Forks
0
Avg merge
1h 7m
Merged PRs (30d)
969

Description

## 现象

同一次工具调用,**同一屏上两处给出相反结论**:

- 展开的执行轨迹里:外层折叠行 `run-trace-entry[data-status="failed"]`,内层工具卡
`data-tool-status="failed"` + 红色感叹号 —— 对的(#3204 ① 已修的那一半)。
- **实时消息流**里(`copilotkit-v2-tool-calls-group`,用户先看到的就是这里):同一次
调用的卡片是 `complete` + **绿色对勾**。

## 根因(已定位到行)

`apps/web/lib/chat-workbench/tool-outcome.ts`:

```ts
export function useToolCardStatus(frameworkStatus: "inProgress" | "executing" | "complete"): ToolCardStatus {
const journal = useJournalToolOutcome();
if (journal === null) return frameworkStatus; // ← 这里
return journal === "failed" ? "failed" : journal === "running" ? "executing" : "complete";
}
```

`JournalToolOutcomeContext` 只由轨迹面板 `apps/web/components/chat/workbench/task-timeline.tsx`
下发。实时消息流的工具卡(`apps/web/components/chat/copilotkit-v2-assistant-message.tsx`)
不在那棵树里 ⇒ 拿到 `null` ⇒ **回落到框架三态**。而框架三态
(`inProgress | executing | complete`,来自 `@copilotkit/react-core/v2`)**没有失败态**,
上游 AG-UI 的 `ToolCallResultEventSchema` 只有 `content`、没有 `error`/`isError`
(`node_modules/@ag-ui/core/dist/index.d.ts`)。于是失败在 `render()` 边界上被丢掉、
又被重新发明成"成功"。

## 为什么这不是「缺省」而是缺口

`tool-outcome.ts` 的头注把这条回落写成「`null` = 不在执行轨迹里,没有事实可用」。
**但这一轮里事实是有的**——同一屏的轨迹面板正拿着它(同一个 runId、同一个 toolCallId)。
不是"没有事实可用",是"这棵树没接上那份事实"。#3204 ① 要收敛的正是这个形状,只收敛了一半。

## 复现

本仓确定性替身已具备(本 PR 新加):`CHAT_READ_E2E.deepAgentToolFailureTrigger`
——run 正常收尾,其中一次工具调用的 ToolMessage 带 `status: "error"`。

## 已落地的门

`apps/web/e2e/chat-path-d1-failed-tool-card-status.spec.ts` 第二条用例逐字写着这条判据,
按本仓既有先例(#2997 方案 B,A3/C8 两次)挂 `test.fixme`:**不删断言、不改宽、
不 `test.skip`**。本 issue 修好后把 `fixme` 改回 `test` 即可,spec 正文一个字不用动。

## 修法方向(未定,供讨论)

把权威状态的下发范围从"轨迹面板这棵树"扩到"这一轮的所有工具卡"——消息流那棵树同样
按 `toolCallId` 能查到执行日志条目,缺的是 provider,不是数据。

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with apps/web/lib/chat-workbench/tool-outcome.ts, then trace how JournalToolOutcomeContext is provided by task-timeline.tsx and consumed by copilotkit-v2-assistant-message.tsx. Run apps/web/e2e/chat-path-d1-failed-tool-card-status.spec.ts and inspect its second test and existing fixme pattern. Done means the real-time card shows failed status for the deterministic tool failure and the fixme can become test without changing the assertion.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.