feat: 【代码回合】subagent流式输出+路径拦截+Office文档+reasoning_content适配 - #464
feat: 【代码回合】subagent流式输出+路径拦截+Office文档+reasoning_content适配#464openjiuwen-sync-bot[bot] wants to merge 1 commit into
Conversation
|
head_sha: 变更摘要本次变更从 主要改动
|
|
head_sha: 代码审查✅ 未发现问题 |
3584fe5 to
3199687
Compare
| ) | ||
| assert agent.ability_manager.get("task_tool") is not None | ||
|
|
||
| agent.react_agent.set_llm(fake_model) |
There was a problem hiding this comment.
head_sha: 31996876d6e403b23ba2e645b182e8a80e0f54fb
[建议][Should Fix][Clean] ruff codecheck FAILED(PR 描述中已标注)。test_expert_harness_hot_load.py 中存在多处连续空行(E303 too many blank lines),可能为 ruff 失败原因之一。建议运行 ruff check --fix 和 ruff format 修复所有格式问题后重新推送。
问题: ruff codecheck FAILED(PR 描述中已标注)。test_expert_harness_hot_load.py 中存在多处连续空行(E303 too many blank lines),可能为 ruff 失败原因之一。建议运行 ruff check --fix 和 ruff format 修复所有格式问题后重新推送。
触发场景: ruff codecheck FAILED(PR 描述中已标注)。test_expert_harness_hot_load.py 中存在多处连续空行(E303 too many blank lines),可能为 ruff 失败原因之一。建议运行 ruff check --fix 和 ruff format 修复所有格式问题后重新推送。
影响: CI ruff 检查不通过,可能阻塞合入。
建议修复: 运行 ruff check --fix tests/unit_tests/harness/test_expert_harness_hot_load.py 和 ruff format tests/unit_tests/harness/test_expert_harness_hot_load.py,修复所有 ruff 告警后重新推送。
验证建议: 补充或执行覆盖该场景的单元测试/回归验证,确认修复后不会再次触发该问题。
本批次回合 agent-core 侧 4 类改动,覆盖流式输出、路径拦截、Office 文档读取 与 reasoning_content 字段适配,均为小修小改,不重构现有架构。 背景:TaskTool 委派子 agent 时仅返回最终结果,父 agent 无法实时看到子 agent 的思考与产出,并行子 agent 的流式输出也无法区分来源。 方案: - TaskTool.invoke 创建子 session 时注入 source_metadata(source_agent_id、 subagent_type、parent_session_id),调用 subagent.stream() 并将每个 chunk 转发到父 session.write_stream(),使前端实时看到子 agent 进度。 - 子 session 携带 source_metadata 后 chunk 自动带 source_agent_id,并行子 agent 流可被前端区分(配合 jiuwenswarm 侧 E2A 透传)。 - 子 session 使用独立 stream_writer_manager,避免共享父 SWM 导致流关闭冲突。 文件:openjiuwen/harness/tools/subagent/task_tool.py 背景:部分大模型 API 要求 assistant 消息携带 reasoning_content 字段,缺失 会导致请求被拒或思考链丢失。 方案: - base_model_client:消息归一化时为所有 assistant 消息补全 reasoning_content=""(dict 形式遍历补全,BaseMessage 形式统一设置)。 - react_agent(legacy):构造 AssistantMessage 时透传 reasoning_content=getattr(llm_output, "reasoning_content", None), 用 getattr 安全取值兼容无此字段的模型。 文件: - openjiuwen/core/foundation/llm/model_clients/base_model_client.py - openjiuwen/core/single_agent/legacy/react_agent.py 背景:restrict_to_work_dir=True 时 sandbox 默认只允许子 agent 自身 workspace, 子 agent 无法读取父 agent 的技能目录(SKILL.md 等)。 方案:resolve_deep_agent_parts / create_deep_agent 增加 allowed_paths 参数, 非 None 时设置 work_config.sandbox_root=allowed_paths,将指定目录纳入沙箱白名单。 参数名 allowed_paths 语义明确无歧义,与现有 sandbox_root 对齐。 文件:openjiuwen/harness/factory.py 背景:ReadFileTool 仅支持文本/图片/PDF/Notebook,无法读取 .docx/.xlsx/.pptx 等 Office 文档,子 agent 处理办公文档时需手动转换。 方案: - 新增 _OFFICE_DOC_EXTENSIONS(.docx/.doc/.xlsx/.xls/.pptx/.ppt)与 _is_office_doc 判断,Office 文档纳入二进制检查豁免。 - 新增 _read_office_doc 分发到 _read_docx/_read_xlsx/_read_pptx, 复用 python-docx/openpyxl/python-pptx 解析,MAX_OFFICE_DOC_SIZE_BYTES 限制 10MB 防止大文件 OOM。 - 更新 READ_FILE_DESCRIPTION 说明 Office 文档支持。 - pyproject.toml 新增 python-pptx>=0.6.23 依赖。 文件: - openjiuwen/harness/tools/filesystem.py - openjiuwen/harness/prompts/tools/filesystem.py - pyproject.toml
3199687 to
31145ba
Compare
Paired: GitHub #464 ↔ GitCode !2285
agent-core PR 描述
What type of PR is this?
/kind feature
Self-checklist:
背景
本批次回合 agent-core 侧 4 个 PR,覆盖子 agent 流式输出、reasoning_content 字段适配、create_deep_agent 路径拦截参数、ReadFileTool Office 文档读取。均为小修小改,不重构现有架构,基于
subagent_box_file_core分支。涉及 PR
方案
PR 1604 / 1981 / 2051 / 1956 — 子 agent 流式输出
背景:TaskTool 委派子 agent 时仅返回最终结果,父 agent 无法实时看到子 agent 的思考与产出,并行子 agent 的流式输出也无法区分来源。
方案:
source_metadata(source_agent_id、subagent_type、parent_session_id),调用subagent.stream()并将每个 chunk 转发到父session.write_stream(),使前端实时看到子 agent 进度。source_metadata后 chunk 自动带source_agent_id(经Session._tag_stream_payload注入 chunk.payload),并行子 agent 流可被前端区分(配合 jiuwenswarm 侧 E2A 透传)。stream_writer_manager,避免共享父 SWM 导致流关闭冲突。链路:
flowchart TD A["TaskTool 创建 child_session<br/>注入 source_metadata(source_agent_id 等)"] B["ReActAgent._inner_stream<br/>调用 child_session.write_stream 写入 chunk"] C["Session._tag_stream_payload<br/>用 source_metadata 注入 chunk.payload"] D["TaskTool 转发 chunk<br/>到 parent_session.write_stream"] E["jiuwenswarm E2A<br/>_parse_stream_chunk 提取 source_agent_id"] A --> B --> C --> D --> E文件:
openjiuwen/harness/tools/subagent/task_tool.pyPR 1179 — reasoning_content 字段适配
背景:部分大模型 API 要求 assistant 消息携带
reasoning_content字段,缺失会导致请求被拒或思考链丢失。方案:
base_model_client:消息归一化时为所有 assistant 消息补全reasoning_content=""(dict 形式遍历补全并浅拷贝避免修改原 dict,BaseMessage 形式统一设置)。react_agent(legacy):构造 AssistantMessage 时透传reasoning_content=getattr(llm_output, "reasoning_content", None),用 getattr 安全取值兼容无此字段的模型。文件:
openjiuwen/core/foundation/llm/model_clients/base_model_client.pyopenjiuwen/core/single_agent/legacy/react_agent.pyPR 1882 — create_deep_agent 增加 allowed_paths 参数
背景:
restrict_to_work_dir=True时 sandbox 默认只允许子 agent 自身 workspace,子 agent 无法读取父 agent 的技能目录(SKILL.md 等)。方案:
resolve_deep_agent_parts/create_deep_agent增加allowed_paths: Optional[List[str]]参数,非 None 时设置work_config.sandbox_root=allowed_paths,将指定目录纳入沙箱白名单。参数名allowed_paths语义明确无歧义,与现有sandbox_root对齐。默认 None,向后兼容。文件:
openjiuwen/harness/factory.pyPR 1899 — ReadFileTool 支持 Office 文档
背景:ReadFileTool 仅支持文本/图片/PDF/Notebook,无法读取
.docx/.xlsx/.pptx等 Office 文档(ZIP 压缩二进制格式),子 agent 处理办公文档时需手动转换。方案:
_OFFICE_DOC_EXTENSIONS(.docx/.doc/.xlsx/.xls/.pptx/.ppt)与_is_office_doc判断,Office 文档纳入二进制检查豁免。_read_office_doc分发到_read_docx/_read_xlsx/_read_pptx,复用python-docx/openpyxl/python-pptx解析。MAX_OFFICE_DOC_SIZE_BYTES = 10MB限制防止大文件 OOM(与旧架构 PR 1899 一致)。.doc/.xls/.ppt明确提示转换为现代格式。ImportError友好提示安装对应包。asyncio.to_thread避免阻塞事件循环。READ_FILE_DESCRIPTION说明 Office 文档支持。pyproject.toml新增python-pptx>=0.6.23依赖。文件:
openjiuwen/harness/tools/filesystem.pyopenjiuwen/harness/prompts/tools/filesystem.pypyproject.toml文件变更
openjiuwen/harness/tools/subagent/task_tool.pyopenjiuwen/core/foundation/llm/model_clients/base_model_client.pyopenjiuwen/core/single_agent/legacy/react_agent.pyopenjiuwen/harness/factory.pyopenjiuwen/harness/tools/filesystem.pyopenjiuwen/harness/prompts/tools/filesystem.pypyproject.toml合计 7 文件,+247/-15。
验证
Linked Closing Issues: