fix(agent): restore ReAct multi-turn user history (#3171) - #3198
fix(agent): restore ReAct multi-turn user history (#3171)#3198mumubuku wants to merge 8 commits into
Conversation
…oros-ai#3171) Each chat_react_agent request built a new agent whose short-term memory did not carry the previous question and final answer, so follow-ups like '上面那个订单' were solved from scratch. Load completed turns from the conversation store and always inject them into thinking messages. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Important Review skippedReview was skipped due to path filters ⛔ Files ignored due to path filters (4)
CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughPurpose and implementationThis change restores multi-turn history for Affected packages and APIs
Risks
VerificationExisting tests are in Recommended verification: pytest packages/dbgpt-app/src/dbgpt_app/openapi/api_v1/tests/test_react_history.pyMissing coverage includes an end-to-end API test that verifies stored history reaches WalkthroughThe change reconstructs bounded ReAct conversation history from stored messages, adds a conditional history hint to workflow prompts, formats follow-up questions with prior turns, and updates base-agent message loading. ChangesReAct history integration
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: 🟡 Moderate · up to The PR restores multi-turn history, but the current head still has a truncation-bound issue that can produce outputs beyond the configured limit, and the related test does not catch it; merge should wait for this bounded correctness gap to be fixed or explicitly accepted. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: a1d801f6-bb52-4308-8d61-0e29e0e8b554
📒 Files selected for processing (5)
packages/dbgpt-app/src/dbgpt_app/openapi/api_v1/agentic_data_api.pypackages/dbgpt-app/src/dbgpt_app/openapi/api_v1/react_history.pypackages/dbgpt-app/src/dbgpt_app/openapi/api_v1/tests/__init__.pypackages/dbgpt-app/src/dbgpt_app/openapi/api_v1/tests/test_react_history.pypackages/dbgpt-core/src/dbgpt/agent/core/base_agent.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use Python 3.10 or newer for project development.
Files:
packages/dbgpt-app/src/dbgpt_app/openapi/api_v1/react_history.pypackages/dbgpt-app/src/dbgpt_app/openapi/api_v1/tests/test_react_history.pypackages/dbgpt-app/src/dbgpt_app/openapi/api_v1/agentic_data_api.pypackages/dbgpt-core/src/dbgpt/agent/core/base_agent.py
packages/dbgpt-app/src/dbgpt_app/**/*.py
⚙️ CodeRabbit configuration file
packages/dbgpt-app/src/dbgpt_app/**/*.py: - dbgpt-app 是组合和启动层。共享 interface、storage abstraction 和
connector implementation 应位于更底层的 package 中。
- 审查 SystemApp 注册、初始化与关闭顺序、全局状态、配置默认值以及启动失败后的清理。
- OpenAPI endpoint、文件上传、GitHub import、skill extraction 和 artifact
download 必须防止绝对路径、父目录遍历、symlink escape、Zip Slip 和 Tar Slip。
必须限制文件数量、单文件大小和总大小。- 不可信的 Python、shell 和任意代码执行必须使用受限 sandbox。不得回退到宿主机
exec、eval、shell=True 或不受限的文件系统访问。SQL 执行应使用 datasource
connector 层,并强制实施参数化、最小权限、适用情况下的只读访问、行数限制和 timeout。- SSE 和 asynchronous generator 必须处理断开连接、取消、timeout、错误、
terminal event、task 清理和用户数据隔离。- 保持 conversation、message、streaming event 和前端消费协议的兼容性,并为
用户可见行为提供回归测试。
Files:
packages/dbgpt-app/src/dbgpt_app/openapi/api_v1/react_history.pypackages/dbgpt-app/src/dbgpt_app/openapi/api_v1/tests/test_react_history.pypackages/dbgpt-app/src/dbgpt_app/openapi/api_v1/agentic_data_api.py
**/{tests/**/*.py,test_*.py,*_test.py}
⚙️ CodeRabbit configuration file
**/{tests/**/*.py,test_*.py,*_test.py}: 检查 Python 测试、fixture 和测试辅助代码是否提供了有意义的回归覆盖。
- 应断言可观察行为和对外相关契约,而不是只断言 mock 调用次数或实现细节。将 mock
保持在真实 I/O 或进程边界,使被测行为本身仍会执行。- 对于 bug 修复,聚焦的回归测试应在旧行为上失败。对于安全修复,在能够安全测试时,
应包含一个具体的绕过方式或恶意输入场景。- 当这些场景与变更的生产路径相关时,覆盖错误、空输入、边界、清理,以及异步取消
或 timeout 行为;不要要求与变更无关的穷尽式覆盖。- 保持单元测试确定且隔离,不依赖真实网络、外部模型、数据库、GPU、Docker、
wall-clock time 或开发者机器状态。确实需要这些资源的测试应位于 integration test
中或明确标记为 integration test,说明其前置条件,并清理创建的资源。- 如果可以使用 event、mock clock、同步原语或有界不变量验证行为,应避免使用 sleep
和脆弱的性能阈值。- 对于聚焦验证,建议运行 uv run pytest 并指定相关测试路径。不要假设 make test 会运行
dbgpt_app、dbgpt_serve、dbgpt_ext、dbgpt_client 或 dbgpt_sandbox 的测试;其当前
target 运行的是 dbgpt package 测试。不要将 make fmt-check 描述为只读命令,因为
当前 target 会调用 ruff check --fix。
Files:
packages/dbgpt-app/src/dbgpt_app/openapi/api_v1/tests/test_react_history.py
packages/dbgpt-core/src/dbgpt/**/*.py
⚙️ CodeRabbit configuration file
packages/dbgpt-core/src/dbgpt/**/*.py: 这是以 dbgpt 名义发布的核心库。
- 严格审查公共 API、构造函数参数、返回类型、Pydantic 字段、序列化格式和异常语义的向后兼容性。
- 不得引入或扩大 core 对 dbgpt_ext、dbgpt_serve、dbgpt_app、dbgpt_client 或
dbgpt_sandbox 的反向依赖。只报告当前 diff 新增或扩大的依赖违规问题。- 对于 AWEL 变更,应同时审查同步、异步和流式执行路径。检查 DAG 关系、
ContextVar 传播、背压、顺序、结束信号、异常传播和取消处理。- 不得在 async 函数中直接执行阻塞式数据库、文件、网络或模型操作。检查连接、
task、thread、generator 和临时资源的清理。- 公共行为变更必须提供邻近的回归测试,并覆盖相关的正常、错误、空输入、并发、
取消或流式场景。
Files:
packages/dbgpt-core/src/dbgpt/agent/core/base_agent.py
🪛 Ruff (0.16.1)
packages/dbgpt-app/src/dbgpt_app/openapi/api_v1/react_history.py
[error] 66-67: try-except-pass detected, consider logging the exception
(S110)
[warning] 66-66: Do not catch blind exception: Exception
(BLE001)
packages/dbgpt-app/src/dbgpt_app/openapi/api_v1/tests/test_react_history.py
[warning] 34-34: String contains ambiguous ? (FULLWIDTH QUESTION MARK). Did you mean ? (QUESTION MARK)?
(RUF001)
[warning] 45-45: String contains ambiguous ? (FULLWIDTH QUESTION MARK). Did you mean ? (QUESTION MARK)?
(RUF001)
[warning] 50-50: String contains ambiguous ? (FULLWIDTH QUESTION MARK). Did you mean ? (QUESTION MARK)?
(RUF001)
[warning] 55-55: String contains ambiguous ? (FULLWIDTH QUESTION MARK). Did you mean ? (QUESTION MARK)?
(RUF001)
…horos-ai#3171) Extra Human history turns can be ignored or re-solved as a new ReAct task. Put previous final answers into the single current question so follow-ups like 上面 resolve from the message the model actually attends to. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 59d910e3-b9bd-4d2b-ab7e-ec6629bdc21b
📒 Files selected for processing (3)
packages/dbgpt-app/src/dbgpt_app/openapi/api_v1/agentic_data_api.pypackages/dbgpt-app/src/dbgpt_app/openapi/api_v1/react_history.pypackages/dbgpt-app/src/dbgpt_app/openapi/api_v1/tests/test_react_history.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use Python 3.10 or newer for project development.
Files:
packages/dbgpt-app/src/dbgpt_app/openapi/api_v1/agentic_data_api.pypackages/dbgpt-app/src/dbgpt_app/openapi/api_v1/react_history.pypackages/dbgpt-app/src/dbgpt_app/openapi/api_v1/tests/test_react_history.py
packages/dbgpt-app/src/dbgpt_app/**/*.py
⚙️ CodeRabbit configuration file
packages/dbgpt-app/src/dbgpt_app/**/*.py: - dbgpt-app 是组合和启动层。共享 interface、storage abstraction 和
connector implementation 应位于更底层的 package 中。
- 审查 SystemApp 注册、初始化与关闭顺序、全局状态、配置默认值以及启动失败后的清理。
- OpenAPI endpoint、文件上传、GitHub import、skill extraction 和 artifact
download 必须防止绝对路径、父目录遍历、symlink escape、Zip Slip 和 Tar Slip。
必须限制文件数量、单文件大小和总大小。- 不可信的 Python、shell 和任意代码执行必须使用受限 sandbox。不得回退到宿主机
exec、eval、shell=True 或不受限的文件系统访问。SQL 执行应使用 datasource
connector 层,并强制实施参数化、最小权限、适用情况下的只读访问、行数限制和 timeout。- SSE 和 asynchronous generator 必须处理断开连接、取消、timeout、错误、
terminal event、task 清理和用户数据隔离。- 保持 conversation、message、streaming event 和前端消费协议的兼容性,并为
用户可见行为提供回归测试。
Files:
packages/dbgpt-app/src/dbgpt_app/openapi/api_v1/agentic_data_api.pypackages/dbgpt-app/src/dbgpt_app/openapi/api_v1/react_history.pypackages/dbgpt-app/src/dbgpt_app/openapi/api_v1/tests/test_react_history.py
**/{tests/**/*.py,test_*.py,*_test.py}
⚙️ CodeRabbit configuration file
**/{tests/**/*.py,test_*.py,*_test.py}: 检查 Python 测试、fixture 和测试辅助代码是否提供了有意义的回归覆盖。
- 应断言可观察行为和对外相关契约,而不是只断言 mock 调用次数或实现细节。将 mock
保持在真实 I/O 或进程边界,使被测行为本身仍会执行。- 对于 bug 修复,聚焦的回归测试应在旧行为上失败。对于安全修复,在能够安全测试时,
应包含一个具体的绕过方式或恶意输入场景。- 当这些场景与变更的生产路径相关时,覆盖错误、空输入、边界、清理,以及异步取消
或 timeout 行为;不要要求与变更无关的穷尽式覆盖。- 保持单元测试确定且隔离,不依赖真实网络、外部模型、数据库、GPU、Docker、
wall-clock time 或开发者机器状态。确实需要这些资源的测试应位于 integration test
中或明确标记为 integration test,说明其前置条件,并清理创建的资源。- 如果可以使用 event、mock clock、同步原语或有界不变量验证行为,应避免使用 sleep
和脆弱的性能阈值。- 对于聚焦验证,建议运行 uv run pytest 并指定相关测试路径。不要假设 make test 会运行
dbgpt_app、dbgpt_serve、dbgpt_ext、dbgpt_client 或 dbgpt_sandbox 的测试;其当前
target 运行的是 dbgpt package 测试。不要将 make fmt-check 描述为只读命令,因为
当前 target 会调用 ruff check --fix。
Files:
packages/dbgpt-app/src/dbgpt_app/openapi/api_v1/tests/test_react_history.py
🪛 Ruff (0.16.1)
packages/dbgpt-app/src/dbgpt_app/openapi/api_v1/tests/test_react_history.py
[warning] 14-14: String contains ambiguous ? (FULLWIDTH QUESTION MARK). Did you mean ? (QUESTION MARK)?
(RUF001)
[warning] 15-15: String contains ambiguous ( (FULLWIDTH LEFT PARENTHESIS). Did you mean ( (LEFT PARENTHESIS)?
(RUF001)
[warning] 15-15: String contains ambiguous ) (FULLWIDTH RIGHT PARENTHESIS). Did you mean ) (RIGHT PARENTHESIS)?
(RUF001)
[warning] 16-16: String contains ambiguous ? (FULLWIDTH QUESTION MARK). Did you mean ? (QUESTION MARK)?
(RUF001)
| def test_extract_keeps_plain_text_and_truncates(): | ||
| assert extract_react_final_content("hello") == "hello" | ||
| assert extract_react_final_content("abcdef", max_chars=5) == "ab..." | ||
|
|
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Cover short truncation limits.
extract_react_final_content("abcdef", max_chars=1) currently returns "abcd...". This exceeds max_chars because the implementation uses a negative slice index. The current test only covers max_chars=5, so it does not detect this boundary failure. Add regression cases for max_chars=1 and max_chars=2, then correct the truncation implementation.
Proposed regression coverage
def test_extract_keeps_plain_text_and_truncates():
assert extract_react_final_content("hello") == "hello"
assert extract_react_final_content("abcdef", max_chars=5) == "ab..."
+ assert len(extract_react_final_content("abcdef", max_chars=1)) <= 1
+ assert len(extract_react_final_content("abcdef", max_chars=2)) <= 2As per path instructions, cover relevant boundary behavior.
Source: Path instructions
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
|
Thanks for your contribution. Please provide before vs after functional proof (screenshots or video) to verify code correctness and the correctness of the functional flow. |
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
|
Thanks for the review. Here is live functional proof on the current branch (not unit-test diagrams). Environment
Unit tests
Covered without the live LLM:
Live UI flow (this is the functional proof)Home / model selected Turn 1 (no prior history) Turn 2 ( UI: assistant answers Turn 3 ( Before vs afterBefore (#3171): each HTTP request builds a new After: completed turns are folded into the current Observation (Q + Not claimed from this live run
|




Summary
chat_react_agentstarts a newReActAgenton every HTTP request. Short-term memory is empty (and GPTs recovery only keeps a 5-step tool buffer), so follow-up questions never saw the previous user question or final answer.StorageConversation, keep onlyfinal_content(not prior tool traces), and always inject them ashistorical_dialogueseven when current-loop memories exist.统计和上面...所属商品) ignored turn 1'sorder_id=3 / sku_id=100result.Test plan
pytest packages/dbgpt-app/src/dbgpt_app/openapi/api_v1/tests/test_react_history.pyconv_uid: ask a question, then a follow-up with上面/刚才; the second prompt should containPrevious question/Previous resultfrom turn 1Made with Cursor