update
This commit is contained in:
@@ -702,6 +702,22 @@ async def set_block_status(topic: str, title_norm: str, status: str, title: str
|
||||
await _update("blocks", fields, {"topic": topic, "title_norm": title_norm})
|
||||
|
||||
|
||||
async def rename_block_norm(topic: str, alt_norm: str, neu_norm: str, neu_titel: str) -> None:
|
||||
"""Block-Norm vollständig um-keyen (Repair: `(n)`-Kollisionssuffix ablegen): blocks-
|
||||
Spiegel PLUS alle angehängten Tabellen in einer Transaktion — anders als
|
||||
set_block_status(neu_norm=…) auch mit vorhandenen Subblocks/Fragen/Artefakten sicher."""
|
||||
async with _tx() as db:
|
||||
for table in ("subblocks", "question_pattern", "sub_artefakte"):
|
||||
await db.execute(
|
||||
f"UPDATE {table} SET block_norm = ?, block = ?, updated_at = ? "
|
||||
"WHERE topic = ? AND block_norm = ?",
|
||||
(neu_norm, neu_titel, _now(), topic, alt_norm))
|
||||
await db.execute(
|
||||
"UPDATE blocks SET title_norm = ?, title = ?, updated_at = ? "
|
||||
"WHERE topic = ? AND title_norm = ?",
|
||||
(neu_norm, neu_titel, _now(), topic, alt_norm))
|
||||
|
||||
|
||||
async def delete_blocks(topic: str) -> None:
|
||||
async with _tx() as db:
|
||||
await db.execute("DELETE FROM blocks WHERE topic = ?", (topic,))
|
||||
@@ -945,6 +961,35 @@ async def list_runs(topic: str, limit: int = 10) -> list[dict]:
|
||||
return out
|
||||
|
||||
|
||||
async def latest_board_runs(topic: str) -> dict:
|
||||
"""Jüngster Lauf MIT Daten je Ebene — Anzeige-Quelle der Board-Kopfzeilen im Frontend.
|
||||
„Nur Artefakte"-/Guide-Läufe bekommen eine frische run_id und lassen die anderen Ebenen
|
||||
leer; der jüngste Lauf allein zeigt dann nichts. Hier zählt je Ebene der letzte Lauf,
|
||||
der sie wirklich enthielt. inventory/artefacts via meta.$.board (agents.agent_ebene);
|
||||
guide via run_id-Suffix „-g"+4hex (guide_board.run_guide_board setzt den Marker,
|
||||
Blocks-Suffixe sind reines Hex — enthalten nie „g").
|
||||
→ {ebene: {run_id, aktiv, agents, tokens, start, ende} | None}"""
|
||||
db = await get_db()
|
||||
out: dict = {}
|
||||
for b in ("inventory", "artefacts"):
|
||||
cur = await db.execute(
|
||||
"SELECT run_id FROM events WHERE topic = ? AND kind = 'agent' AND run_id != '' "
|
||||
"AND json_extract(meta,'$.board') = ? ORDER BY ts DESC LIMIT 1", (topic, b))
|
||||
row = await cur.fetchone()
|
||||
out[b] = None if row is None else {
|
||||
"run_id": row[0], "aktiv": _current_run.get(topic) == row[0],
|
||||
**await events_run_summary(topic, row[0], board=b)}
|
||||
cur = await db.execute(
|
||||
"SELECT run_id FROM events WHERE topic = ? AND kind = 'agent' AND run_id != '' "
|
||||
"AND run_id GLOB '*-g[0-9a-f][0-9a-f][0-9a-f][0-9a-f]' ORDER BY ts DESC LIMIT 1",
|
||||
(topic,))
|
||||
row = await cur.fetchone()
|
||||
out["guide"] = None if row is None else {
|
||||
"run_id": row[0], "aktiv": _current_run.get(topic) == row[0],
|
||||
**await events_run_summary(topic, row[0])} # Guide: ganzer Lauf (Events sind untagged)
|
||||
return out
|
||||
|
||||
|
||||
async def kanban_dead(topic: str) -> list[dict]:
|
||||
"""Dead-letter cards across boards (for the board UI + requeue)."""
|
||||
return await kanban_cards(topic, stage="dead")
|
||||
|
||||
Reference in New Issue
Block a user