auto-sync: 2026-05-19 13:54:26
This commit is contained in:
@@ -682,3 +682,134 @@ class Blackboard:
|
|||||||
finally:
|
finally:
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
|
||||||
|
# ── Checkpoint CRUD(M3) ──
|
||||||
|
|
||||||
|
def create_checkpoint(
|
||||||
|
self,
|
||||||
|
task_id: str,
|
||||||
|
cp_type: str,
|
||||||
|
title: str,
|
||||||
|
payload: dict,
|
||||||
|
description: str | None = None,
|
||||||
|
checkpoint_id: str | None = None,
|
||||||
|
) -> dict:
|
||||||
|
"""创建 Checkpoint"""
|
||||||
|
import uuid
|
||||||
|
cp_id = checkpoint_id or f"cp-{uuid.uuid4().hex[:8]}"
|
||||||
|
conn = self._conn()
|
||||||
|
try:
|
||||||
|
conn.execute("BEGIN IMMEDIATE")
|
||||||
|
conn.execute(
|
||||||
|
"INSERT INTO checkpoints (id, task_id, type, title, description, payload) "
|
||||||
|
"VALUES (?,?,?,?,?,?)",
|
||||||
|
(cp_id, task_id, cp_type, title, description, json.dumps(payload)),
|
||||||
|
)
|
||||||
|
conn.execute(
|
||||||
|
"INSERT INTO events (task_id, agent, event_type, detail) VALUES (?,?,?,?)",
|
||||||
|
(task_id, "daemon", "checkpoint_created",
|
||||||
|
json.dumps({"checkpoint_id": cp_id, "type": cp_type, "title": title})),
|
||||||
|
)
|
||||||
|
conn.commit()
|
||||||
|
return {"id": cp_id, "task_id": task_id, "type": cp_type,
|
||||||
|
"title": title, "status": "pending"}
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def list_checkpoints(self, task_id: str) -> list[dict]:
|
||||||
|
"""列出 task 的所有 checkpoint"""
|
||||||
|
conn = self._conn()
|
||||||
|
try:
|
||||||
|
rows = conn.execute(
|
||||||
|
"SELECT * FROM checkpoints WHERE task_id=? ORDER BY created_at",
|
||||||
|
(task_id,),
|
||||||
|
).fetchall()
|
||||||
|
return [dict(r) for r in rows]
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def get_checkpoint(self, checkpoint_id: str) -> dict | None:
|
||||||
|
"""获取单个 checkpoint"""
|
||||||
|
conn = self._conn()
|
||||||
|
try:
|
||||||
|
row = conn.execute(
|
||||||
|
"SELECT * FROM checkpoints WHERE id=?", (checkpoint_id,)
|
||||||
|
).fetchone()
|
||||||
|
return dict(row) if row else None
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def resolve_checkpoint(
|
||||||
|
self,
|
||||||
|
checkpoint_id: str,
|
||||||
|
action: str,
|
||||||
|
resolved_by: str = "user",
|
||||||
|
note: str | None = None,
|
||||||
|
) -> dict | None:
|
||||||
|
"""通过/驳回 checkpoint,并自动推进 task 状态
|
||||||
|
|
||||||
|
approve: verify → done, decision/action → working
|
||||||
|
reject: 一律 → working
|
||||||
|
"""
|
||||||
|
conn = self._conn()
|
||||||
|
try:
|
||||||
|
conn.execute("BEGIN IMMEDIATE")
|
||||||
|
row = conn.execute(
|
||||||
|
"SELECT * FROM checkpoints WHERE id=?", (checkpoint_id,)
|
||||||
|
).fetchone()
|
||||||
|
if not row:
|
||||||
|
return None
|
||||||
|
cp = dict(row)
|
||||||
|
if cp["status"] != "pending":
|
||||||
|
return {"error": f"Checkpoint already {cp['status']}"}
|
||||||
|
|
||||||
|
# 更新 checkpoint 状态
|
||||||
|
new_status = "approved" if action == "approve" else "rejected"
|
||||||
|
conn.execute(
|
||||||
|
"UPDATE checkpoints SET status=?, resolved_at=datetime('now'), "
|
||||||
|
"resolved_by=?, resolve_note=? WHERE id=?",
|
||||||
|
(new_status, resolved_by, note, checkpoint_id),
|
||||||
|
)
|
||||||
|
|
||||||
|
# 推进 task 状态
|
||||||
|
task_id = cp["task_id"]
|
||||||
|
cp_type = cp["type"]
|
||||||
|
task_row = conn.execute(
|
||||||
|
"SELECT status FROM tasks WHERE id=?", (task_id,)
|
||||||
|
).fetchone()
|
||||||
|
if not task_row:
|
||||||
|
conn.commit()
|
||||||
|
return {"error": "Task not found"}
|
||||||
|
|
||||||
|
task_status = task_row["status"]
|
||||||
|
if action == "approve":
|
||||||
|
if cp_type == "verify":
|
||||||
|
new_task_status = "done"
|
||||||
|
else:
|
||||||
|
new_task_status = "working"
|
||||||
|
else:
|
||||||
|
new_task_status = "working"
|
||||||
|
|
||||||
|
conn.execute(
|
||||||
|
"UPDATE tasks SET status=?, updated_at=datetime('now') WHERE id=?",
|
||||||
|
(new_task_status, task_id),
|
||||||
|
)
|
||||||
|
conn.execute(
|
||||||
|
"INSERT INTO events (task_id, agent, event_type, detail) VALUES (?,?,?,?)",
|
||||||
|
(task_id, resolved_by, f"checkpoint_{new_status}",
|
||||||
|
json.dumps({
|
||||||
|
"checkpoint_id": checkpoint_id,
|
||||||
|
"action": action,
|
||||||
|
"task_status": new_task_status,
|
||||||
|
"note": note,
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
conn.commit()
|
||||||
|
return {
|
||||||
|
"checkpoint_id": checkpoint_id,
|
||||||
|
"checkpoint_status": new_status,
|
||||||
|
"task_id": task_id,
|
||||||
|
"task_status": new_task_status,
|
||||||
|
}
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
|
|||||||
Reference in New Issue
Block a user