feat(sub_agent): 交付目录改为可选,未指定时自动创建

deliverables_dir 移出必填:留空时自动在 .astrion/sub_agent_results/ 下创建(撞名自动加后缀),最终路径作为工具结果返回;显式传入已存在目录仍报错。

Co-authored-by: Astrion powered by DeepSeek-V4-Flash <astrion-agent@users.noreply.github.com>
This commit is contained in:
JOJO 2026-08-29 23:11:54 +08:00
parent 04770e0af9
commit 10a2763f00
3 changed files with 20 additions and 8 deletions

View File

@ -133,7 +133,7 @@ class ToolsDefinitionAgentToolsMixin:
},
"deliverables_dir": {
"type": "string",
"description": "交付文件夹的相对路径(相对于项目根目录)。子智能体会将所有结果文件放在此目录。\n\n要求:必须是不存在的新目录;若目录不存在会自动创建;若目录已存在(无论是否为空)将报错。\n\n留空则使用默认路径sub_agent_results/agent_{agent_id}\n\n示例:'docs/api''reports/performance''tests/generated'"
"description": "交付文件夹的相对路径(相对于项目根目录)。子智能体会将所有结果文件放在此目录。\n\n显式传入时:必须是不存在的新目录,若已存在(无论是否为空)将报错。\n\n留空时:自动在 .astrion/sub_agent_results/ 下创建(如 agent_{agent_id}),最终路径会作为工具结果返回。\n\n示例:'docs/api''reports/performance''tests/generated'"
},
"run_in_background": {
"type": "boolean",
@ -149,7 +149,7 @@ class ToolsDefinitionAgentToolsMixin:
"description": "子智能体思考模式,根据任务复杂度选择:\n\nfast快速模式- 适合简单明确的任务:\n- 网络信息搜集和整理\n- 批量文件读取和简单处理\n- 执行已知的命令序列\n- 生成简单的文档或报告\n- 数据格式转换\n\nthinking思考模式- 适合复杂任务:\n- 代码架构分析和重构设计\n- 复杂算法实现和优化\n- 多步骤问题诊断和调试\n- 技术方案选型和对比\n- 需要深度推理的代码审查\n\n不填则使用默认模式。"
}
}),
"required": ["agent_id", "summary", "task", "deliverables_dir", "thinking_mode"]
"required": ["agent_id", "summary", "task", "thinking_mode"]
}
}
},

View File

@ -103,22 +103,22 @@ class SubAgentCreationMixin:
return "任务摘要不能为空"
if not task or not task.strip():
return "任务详情不能为空"
# 多智能体模式不需要交付目录
if not multi_agent_mode and target_dir is None:
return "指定文件夹不能为空"
# 交付目录不再必填:传统模式未指定时自动创建(见 _resolve_deliverables_dir
return None
def _generate_task_id(self, agent_id: int) -> str:
suffix = uuid.uuid4().hex[:6]
return f"sub_{agent_id}_{int(time.time())}_{suffix}"
def _resolve_deliverables_dir(self, relative_dir: Optional[str], *, multi_agent_mode: bool = False) -> Path:
def _resolve_deliverables_dir(self, relative_dir: Optional[str], *, agent_id: int = 0, multi_agent_mode: bool = False) -> Path:
relative_dir = (relative_dir or "").strip()
# 多智能体模式:没有交付目录概念,直接使用项目根目录
if multi_agent_mode and not relative_dir:
return self.project_path.resolve()
if not relative_dir:
raise ValueError(tr("sub_agent_creation.deliverables_dir_required"))
# 未显式指定交付目录:在运行时目录 .astrion/sub_agent_results/ 下自动创建
#(撞名自动加后缀,保证总能建成),实际路径由 create_sub_agent 结果返回
return self._auto_deliverables_dir(agent_id)
deliverables_path = (self.project_path / relative_dir).resolve()
if not str(deliverables_path).startswith(str(self.project_path)):
raise ValueError(tr("sub_agent_creation.deliverables_dir_outside"))
@ -126,3 +126,15 @@ class SubAgentCreationMixin:
raise ValueError(tr("sub_agent_creation.deliverables_dir_not_new"))
deliverables_path.mkdir(parents=True, exist_ok=True)
return deliverables_path
def _auto_deliverables_dir(self, agent_id: int) -> Path:
"""未指定交付目录时自动创建:.astrion/sub_agent_results/agent_{id}(撞名追加后缀)。"""
base = (self.project_path / ".astrion" / "sub_agent_results").resolve()
base.mkdir(parents=True, exist_ok=True)
candidate = base / f"agent_{agent_id}"
suffix = 2
while candidate.exists():
candidate = base / f"agent_{agent_id}_{suffix}"
suffix += 1
candidate.mkdir(parents=True, exist_ok=True)
return candidate

View File

@ -284,7 +284,7 @@ class SubAgentManager(SubAgentStateMixin, SubAgentStatsMixin, SubAgentCreationMi
task_root.mkdir(parents=True, exist_ok=True)
try:
deliverables_path = self._resolve_deliverables_dir(deliverables_dir, multi_agent_mode=multi_agent_mode)
deliverables_path = self._resolve_deliverables_dir(deliverables_dir, agent_id=agent_id, multi_agent_mode=multi_agent_mode)
except ValueError as exc:
# 回滚已创建的任务目录,避免残留状态(交付目录校验失败时 deliverables 不会创建)
shutil.rmtree(task_root, ignore_errors=True)