fix: 修复上下文持久化与 Dashboard 状态问题#9279
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces several enhancements and bug fixes across the agent runner, provider, and dashboard modules. Key updates include preserving complete conversation history for persistence in ToolLoopAgentRunner, refactoring pop_record in Provider to correctly remove the oldest complete conversation turn, adding a global exception handler to the dashboard API, and fixing a bug in skill archive naming when version numbers contain dots. The review feedback correctly identifies a potential AttributeError in pop_record if the context contains Message objects instead of dictionaries, suggesting a robust helper function to handle both types.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| first_message_index = next( | ||
| ( | ||
| index | ||
| for index, record in enumerate(context) | ||
| if record.get("role") != "system" | ||
| ), | ||
| None, | ||
| ) | ||
| if first_message_index is None: | ||
| return | ||
|
|
||
| next_user_index = next( | ||
| ( | ||
| index | ||
| for index in range(first_message_index + 1, len(context)) | ||
| if context[index].get("role") == "user" | ||
| ), | ||
| len(context), | ||
| ) | ||
| context[:] = [ | ||
| record | ||
| for index, record in enumerate(context) | ||
| if not ( | ||
| first_message_index <= index < next_user_index | ||
| and record.get("role") != "system" | ||
| ) | ||
| ] |
There was a problem hiding this comment.
在 pop_record 中,如果 context 列表中包含的是 Message 对象(例如 Pydantic 模型)而不是原始的 dict,直接调用 record.get("role") 会抛出 AttributeError。建议实现一个辅助函数 _get_role,兼容处理 dict 和具有 role 属性的对象,以提高代码的健壮性。
def _get_role(msg):
if isinstance(msg, dict):
return msg.get("role")
return getattr(msg, "role", None)
first_message_index = next(
(
index
for index, record in enumerate(context)
if _get_role(record) != "system"
),
None,
)
if first_message_index is None:
return
next_user_index = next(
(
index
for index in range(first_message_index + 1, len(context))
if _get_role(context[index]) == "user"
),
len(context),
)
context[:] = [
record
for index, record in enumerate(context)
if not (
first_message_index < index < next_user_index
and _get_role(record) != "system"
)
]
Closes #9278
变更说明
本 PR 优先处理一组共享可靠性问题:
assistant(tool_calls)与tool消息配对。.的 Skill 名称生成 ZIP 时文件名被截断的问题。file://URI 测试,使断言符合本地文件系统路径语义。关联问题
验证结果
uv run pytest tests/test_openai_source.py tests/agent/test_tool_loop_runner_history.py tests/unit/test_skills_service.py tests/test_fastapi_v1_dashboard.py -qpnpm typecheckuv run ruff format .uv run ruff check .完整测试说明
Windows 本地执行完整 pytest 时,在测试收集阶段触发原生 access violation,堆栈涉及 APScheduler 后台线程,尚未进入本 PR 修改的测试。上述定向测试均已通过,完整 Linux CI 结果以 GitHub Actions 为准。
Summary by Sourcery
Separate agent request context trimming from persistent conversation history, improve OpenAI-compatible context trimming behavior, and harden dashboard and provider management reliability.
Bug Fixes:
Enhancements:
Tests: