feat: 任务列表显示 turn_id 与 root_turn_id

host.py dispatch 打印补 turn_id/root_turn_id;执行器解析(local/Docker)透传;worker 写回 tasks 新列(新值非空才覆盖);server 迁移与接口字段;控制台任务列表新增 turn/root turn 两列(短显+悬停全文);新单测 9 个。
This commit is contained in:
host committed 2026-10-27 14:52:00 +08:00
1 parent 559a7dcb9f
commit dbcc8e641a
7 files changed
+252 -11

No files matched your search

+29 -6
View File
@@ -607,7 +607,12 @@ class Worker:
"plan": "INTEGER",
"forked_from": "TEXT",
"environment_id": "TEXT",
"resume_message": "TEXT"}.items():
"resume_message": "TEXT",
# 任务列表显示 turn 用:本任务最近一轮产出过
# turn_id 的回合编号(local/Docker 两路都经
# _result_from_runner/_parse_host_result 提取)。
"turn_id": "TEXT",
"root_turn_id": "TEXT"}.items():
if name not in cols:
try:
conn.execute(
@@ -640,8 +645,15 @@ class Worker:
def _write_execution_result(self, task_id, result_text=None,
error_text=None, actual_model=None,
started_at=None, finished_at=None,
child_pid=None):
"""把执行结果写进 tasks 新列;老库缺列时先迁移再写。"""
child_pid=None, turn_id=None,
root_turn_id=None):
"""把执行结果写进 tasks 新列;老库缺列时先迁移再写。
turn_id/root_turn_id 只在新值非空时覆盖:某轮没产出
turn(如提前失败门、解析不到 JSON)时保留上一轮的值,
列表里始终显示最近一个真实回合的编号,而不是被空值
洗掉。
"""
conn = _db_connect(self.db_path)
try:
self._ensure_result_columns(conn)
@@ -649,20 +661,27 @@ class Worker:
conn.execute(
"UPDATE tasks SET result_text = ?, error_text = ?,"
" actual_model = ?, started_at = ?, finished_at = ?,"
" turn_id = COALESCE(?, turn_id),"
" root_turn_id = COALESCE(?, root_turn_id),"
" updated_at = ? WHERE id = ?",
((result_text or "")[:4000] if result_text else None,
(error_text or "")[:4000] if error_text else None,
actual_model, started_at, finished_at,
turn_id, root_turn_id,
time.time(), task_id),
)
else:
conn.execute(
"UPDATE tasks SET result_text = ?, error_text = ?,"
" actual_model = ?, started_at = ?, finished_at = ?,"
" child_pid = ?, updated_at = ? WHERE id = ?",
" child_pid = ?,"
" turn_id = COALESCE(?, turn_id),"
" root_turn_id = COALESCE(?, root_turn_id),"
" updated_at = ? WHERE id = ?",
((result_text or "")[:4000] if result_text else None,
(error_text or "")[:4000] if error_text else None,
actual_model, started_at, finished_at, child_pid,
turn_id, root_turn_id,
time.time(), task_id),
)
conn.commit()
@@ -2330,7 +2349,9 @@ class Worker:
self._write_execution_result(
task_id, result_text=(result or {}).get("stdout", ""),
error_text="cancelled", actual_model=actual_model,
started_at=started_at, finished_at=time.time())
started_at=started_at, finished_at=time.time(),
turn_id=(result or {}).get("turn_id"),
root_turn_id=(result or {}).get("root_turn_id"))
log_event(self.logger, "worker_cancelled", task_id=task_id,
project_id=task["project_id"], status="interrupted")
return {"dispatched": True, "task_id": task_id,
@@ -2397,7 +2418,9 @@ class Worker:
self._write_execution_result(
task_id, result_text=stdout, error_text=error,
actual_model=actual_model, started_at=started_at,
finished_at=finished_at)
finished_at=finished_at,
turn_id=(result or {}).get("turn_id"),
root_turn_id=(result or {}).get("root_turn_id"))
# 附件暂存清理:任务终局后删 bundle 目录(重试走已存在
# 续跑,文件已在 worktree 里,不再需要暂存)。
self._cleanup_task_seed(task)