boardx / boardx/workspacex

fix(chat): copilotkit-agui onStep 位置游标丢更新——search_documents 结果文本稳定复现为空

Open
#2,016 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

## 发现于

deepagent-capability-rubric.md 第三轮独立重评(2026-08-25,SHA 7d2802b1),
D2 维度打分过程中读到 `apps/web/e2e/copilotkit-v2-tool-rendering.spec.ts`
文件头「已知限制③」——DA-19c 作者自己实测发现并如实登记、但明确标注
「不在本任务范围内修」的一个真实生产缺陷,本 issue 是把它从代码注释提升为
正式 issue(登记,不是本次评分任务顺手改代码)。

## 现象

`search_documents`/`read_document` 的 `TOOL_CALL_RESULT.content` 在多步剧本下
稳定复现为空字符串(spec 头注记录 4/4 次实测),即使数据库层
(`pg_agent_run_repository.ts` 折叠查询)能选出真实终态结果文本。

## 根因(spec 头注里的初步定位,未做代码改动验证)

1. `agui-bridge.ts` 的 `RunStepPublic` 契约不携带 `toolCallId`——同一个逻辑
工具调用的 `in_progress`/`succeeded` 两次上报在 AG-UI 层没有稳定 id 关联。
2. `agui-bridge.ts` 的 `onStep` 用 `projection.steps.slice(reportedStepCount)`
(纯长度游标)判断"这次轮询有没有新 step"——但 `pg-agent-run-repository.ts`
的折叠查询按"胜出行的 seq"重新排序整个数组,同一个 `tool_call_id` 从
`in_progress` 行胜出切换到 `succeeded` 行胜出时,它在数组里的位置会前移到
更靠后,数组总长度不变——一旦这个位置已被 `reportedStepCount` 跨过,那次
"从 in_progress 变成 succeeded、真正带着结果文本"的更新就再也不会进入
`slice(reportedStepCount)`,`onStep` 只看到过第一次(`in_progress`,
`toolResultSummary` 恒为 `null`)的版本。
3. `copilotkit-agui.controller.ts` 的 `writeToolCallStep` 收到任何
`RunStepPublic`(不区分 `status`)都无条件发送完整的
`TOOL_CALL_START→ARGS→END→RESULT→STEP_FINISHED` 序列——该文件自己的注释
"Every RunStepPublic ... is ALREADY COMPLETE by the time onStep fires"
是 #742 Gap 1(引入真实 `in_progress` 上报)之前的前提,Gap 1 落地时没有
同步更新这段注释和逻辑:一个真正"进行中"的 `RunStepPublic` 也会被当作
已终结的调用发出去(`content` 用 `toolResultSummary ?? ""`,此刻恒为
`""`),于是 CopilotKit 客户端看到的是一个"已完成但结果为空"的假终态。

## 为什么值得单独修

这不是伪造(内容是诚实的空字符串,不是编造结果),但用户体验上是「一个
工具调用报告说完成了,结果却是空的」——比"还在等"更容易被误读成"这个工具
调用失败/没干活"。deepagent-capability-rubric.md D2 维度(工具调用透明度)
把这类"状态转换保真度"缺口列为不给满分的理由之一。

## 复现

`apps/web/e2e/copilotkit-v2-tool-rendering.spec.ts` test 2(`search_documents`
定制卡片)——文件头已有完整取证方法(`page.route()+route.fetch()` 抓原始
SSE 字节)。

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with apps/web/e2e/copilotkit-v2-tool-rendering.spec.ts, agui-bridge.ts, copilotkit-agui.controller.ts, and pg-agent-run-repository.ts to trace the reproduced multi-step update. Run test 2 with the file's page.route()+route.fetch() SSE capture. Done means search_documents/read_document preserves the terminal result text instead of reporting a completed step with empty content.

Written by the indexing model from the issue text.

Assessment

Tech stack
postgresql, typescript
Domain
api, backend, testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.