feat:增强需求澄清与任务管理功能

更新了 .env.example,新增聊天模型配置,以提升对话处理能力。
增强了 README.md,反映了包括需求澄清、代码复用和自动重试在内的新功能。
重构了 agent.py,以支持多模型交互,并为无法在本地执行的任务新增了引导处理逻辑。
改进了 SandboxRunner,增加了任务执行成功校验,并加入了工作区清理功能。

扩展了 HistoryManager,支持任务摘要生成以及记录的批量删除。
优化了 chat_view.py 和 history_view.py 中的 UI 组件,提升用户体验,包括 Markdown 渲染和任务管理选项。
This commit is contained in:
Mimikko-zeus
2026-01-07 12:35:27 +08:00
parent 0a92355bfb
commit 68f4f01cd7
12 changed files with 3158 additions and 160 deletions

View File

@@ -119,8 +119,15 @@ class SandboxRunner:
duration_ms=duration_ms
)
# 判断是否成功return code 为 0 且没有明显的失败迹象
success = self._check_execution_success(
result.returncode,
result.stdout,
result.stderr
)
return ExecutionResult(
success=result.returncode == 0,
success=success,
task_id=task_id,
stdout=result.stdout,
stderr=result.stderr,
@@ -187,6 +194,99 @@ class SandboxRunner:
short_uuid = uuid.uuid4().hex[:6]
return f"{timestamp}_{short_uuid}"
def clear_workspace(self, clear_input: bool = True, clear_output: bool = True) -> None:
"""
清空工作目录
Args:
clear_input: 是否清空 input 目录
clear_output: 是否清空 output 目录
"""
if clear_input:
self._clear_directory(self.input_dir)
if clear_output:
self._clear_directory(self.output_dir)
def _clear_directory(self, directory: Path) -> None:
"""
清空目录中的所有文件和子目录
Args:
directory: 要清空的目录路径
"""
if not directory.exists():
return
import shutil
for item in directory.iterdir():
try:
if item.is_file():
item.unlink()
elif item.is_dir():
shutil.rmtree(item)
except Exception as e:
# 忽略删除失败的文件(可能被占用)
print(f"Warning: Failed to delete {item}: {e}")
def _check_execution_success(self, return_code: int, stdout: str, stderr: str) -> bool:
"""
检查执行是否成功
判断逻辑:
1. return code 必须为 0
2. 检查输出中是否有失败迹象
3. 如果有成功和失败的统计,根据失败数量判断
"""
# return code 不为 0 直接判定失败
if return_code != 0:
return False
# 检查 stderr 是否有内容(通常表示有错误)
if stderr and stderr.strip():
# 如果 stderr 有实质内容,可能是失败
# 但有些程序会把警告也输出到 stderr所以不直接判定失败
pass
# 检查 stdout 中的失败迹象
output = stdout.lower() if stdout else ""
# 查找失败统计模式,如 "失败 27 个" 或 "failed: 27"
import re
# 中文模式:成功 X 个, 失败 Y 个
pattern_cn = r'成功\s*(\d+)\s*个.*失败\s*(\d+)\s*个'
match = re.search(pattern_cn, stdout if stdout else "")
if match:
success_count = int(match.group(1))
fail_count = int(match.group(2))
# 如果有失败的,判定为失败
if fail_count > 0:
return False
return True
# 英文模式success: X, failed: Y
pattern_en = r'success[:\s]+(\d+).*fail(?:ed)?[:\s]+(\d+)'
match = re.search(pattern_en, output)
if match:
success_count = int(match.group(1))
fail_count = int(match.group(2))
if fail_count > 0:
return False
return True
# 检查是否有明显的失败关键词
failure_keywords = ['失败', 'error', 'exception', 'traceback', 'failed']
for keyword in failure_keywords:
if keyword in output:
# 如果包含失败关键词,进一步检查是否是统计信息
# 如果是 "失败 0 个" 这种,不算失败
if '失败 0' in stdout or '失败: 0' in stdout or 'failed: 0' in output or 'failed 0' in output:
continue
return False
return True
def _get_safe_env(self) -> dict:
"""获取安全的环境变量(移除网络代理等)"""
safe_env = os.environ.copy()