feat: improve batch task controls and release 1.2.0
This commit is contained in:
1 parent
0e13bb5c29
commit
84e183d28d
38 files changed
+632
-147
No files matched your search
@@ -22,6 +22,7 @@ from artemis.config import IMAGES_DIR, TRACES_PATH, WORKSPACE_ROOT
|
||||
from apps.admin_console.database.repositories.session_repository import SessionRepository
|
||||
from apps.admin_console.database.repositories.step_repository import StepRepository
|
||||
from apps.admin_console.services.automation_store import store, identifier
|
||||
from apps.admin_console.services.task_import import case_title
|
||||
|
||||
EXPORT_ROOT = WORKSPACE_ROOT / "artifacts" / "reports"
|
||||
EXPORT_LOCK = threading.RLock()
|
||||
@@ -40,6 +41,14 @@ STATUS = {
|
||||
}
|
||||
|
||||
|
||||
def archive_case_name(report: dict) -> str:
|
||||
"""Keep case identifiers readable without allowing ZIP paths or Windows-invalid names."""
|
||||
fallback = str(report.get("id") or "task")[:8]
|
||||
candidate = str(report.get("case_id") or fallback).strip()
|
||||
candidate = re.sub(r'[\\/:*?"<>|\x00-\x1f]', "_", candidate).strip(" .")
|
||||
return candidate[:80] or fallback
|
||||
|
||||
|
||||
def read_json(path: Path, fallback=None):
|
||||
try:
|
||||
return json.loads(path.read_text(encoding="utf-8"))
|
||||
@@ -83,6 +92,9 @@ def failure_reason(directory: Path, status: str, recorded: str | None) -> str:
|
||||
return redact(recorded)
|
||||
if status not in {"failed", "interrupted"}:
|
||||
return ""
|
||||
state = read_json(directory / "status.json", {})
|
||||
if isinstance(state, dict) and state.get("error"):
|
||||
return redact(state["error"])
|
||||
for name in ("stdout.log", "stderr.log"):
|
||||
path = directory / name
|
||||
try:
|
||||
@@ -96,6 +108,8 @@ def failure_reason(directory: Path, status: str, recorded: str | None) -> str:
|
||||
match = re.search(r"Error running automation:\s*(.+)", line)
|
||||
if match:
|
||||
return redact(match.group(1))
|
||||
if re.search(r"(?i)(?:timeout|timed out|超时|deadline exceeded)", line):
|
||||
return redact("模型请求或任务执行超时:" + line.strip())
|
||||
return "任务未完成,运行日志中没有可提取的具体异常;请查看执行步骤。"
|
||||
|
||||
|
||||
@@ -142,7 +156,7 @@ def session_report(session_id: str, db_path=None) -> dict:
|
||||
)
|
||||
return {
|
||||
"id": session_id,
|
||||
"name": case.get("name") or session.get("initial_goal", session_id)[:120],
|
||||
"name": case_title(case) or session.get("initial_goal", session_id)[:120],
|
||||
"goal": case.get("goal") or session.get("initial_goal", ""),
|
||||
"expected": case.get("expected", ""),
|
||||
"status": status,
|
||||
@@ -638,15 +652,18 @@ def export_session_media(session_id: str, kind: str) -> Path:
|
||||
"videos": [name for _, name in videos],
|
||||
"note": "录屏按时间顺序分段;暂停期间未占用设备,也未录制其他任务。",
|
||||
}
|
||||
prefix = archive_case_name(report) + "/" if kind == "all" else ""
|
||||
with zipfile.ZipFile(temporary, "w", zipfile.ZIP_DEFLATED) as archive:
|
||||
if kind == "all":
|
||||
for path in export_session(session_id, ["docx", "xlsx"]):
|
||||
archive.write(path, path.name)
|
||||
archive.write(path, prefix + path.name)
|
||||
for source, name in images:
|
||||
archive.write(source, f"步骤截图/{name}")
|
||||
archive.write(source, f"{prefix}步骤截图/{name}")
|
||||
for source, name in videos:
|
||||
archive.write(source, f"任务录屏/{name}")
|
||||
archive.writestr("文件清单.json", json.dumps(manifest, ensure_ascii=False, indent=2))
|
||||
archive.write(source, f"{prefix}任务录屏/{name}")
|
||||
archive.writestr(
|
||||
prefix + "文件清单.json", json.dumps(manifest, ensure_ascii=False, indent=2)
|
||||
)
|
||||
temporary.replace(target)
|
||||
return target
|
||||
|
||||
@@ -691,6 +708,8 @@ def export_batch(batch_id: str) -> Path:
|
||||
archive.write(path, path.name)
|
||||
for number, report in enumerate(records, 1):
|
||||
for path in export_session(report["id"], formats):
|
||||
archive.write(path, f"任务报告/{number:04d}_{report['id']}/{path.name}")
|
||||
archive.write(
|
||||
path, f"任务报告/{number:04d}_{archive_case_name(report)}/{path.name}"
|
||||
)
|
||||
temporary.replace(target)
|
||||
return target
|
||||
Reference in new issue
Block a user