mirror of
https://github.com/razzant/ouroboros.git
synced 2026-10-03 04:07:04 +00:00
fix(review): preserve typed terminal facts and routes
Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
This commit is contained in:
parent
8e20368cca
commit
89e32db656
7 changed files with 74 additions and 3 deletions
|
|
@ -880,6 +880,8 @@ def _collect_chat_rows(
|
|||
rec["mime"] = str(entry.get("mime") or "")
|
||||
rec["download_url"] = str(entry["download_url"])
|
||||
rec["caption"] = str(entry.get("caption") or "")
|
||||
if "task_terminal_status" in entry:
|
||||
rec["task_terminal_status"] = str(entry.get("task_terminal_status") or "")
|
||||
_copy_task_summary_metadata(rec, entry)
|
||||
for field in SUBAGENT_MESSAGE_FIELDS:
|
||||
if field in entry:
|
||||
|
|
|
|||
|
|
@ -43,9 +43,13 @@ def _emit_plan_review_reference(
|
|||
serialized = json.dumps(state, ensure_ascii=False, sort_keys=True, default=str)
|
||||
revision = sha256(serialized.encode("utf-8")).hexdigest()
|
||||
try:
|
||||
chat_id = int(getattr(ctx, "current_chat_id", 0))
|
||||
from supervisor.message_bus import notification_chat_route
|
||||
|
||||
chat_id = notification_chat_route(getattr(ctx, "current_chat_id", None), 1)
|
||||
if chat_id is None:
|
||||
chat_id = 1
|
||||
except (TypeError, ValueError):
|
||||
chat_id = 0
|
||||
chat_id = 1
|
||||
ts = utc_now_iso()
|
||||
payload = {
|
||||
"type": "review_reference", "surface": "plan_review",
|
||||
|
|
|
|||
|
|
@ -915,6 +915,8 @@ def log_chat(
|
|||
for key in ("project_id", "project_name", "target_label", "status"):
|
||||
if key in meta:
|
||||
record[key] = meta[key]
|
||||
if "task_terminal_status" in meta:
|
||||
record["task_terminal_status"] = str(meta.get("task_terminal_status") or "")
|
||||
if filename:
|
||||
record["filename"] = filename
|
||||
if mime:
|
||||
|
|
|
|||
|
|
@ -1479,7 +1479,12 @@ def _run_chat_task(
|
|||
)
|
||||
except Exception:
|
||||
log.debug("Failed-turn typing announce failed", exc_info=True)
|
||||
send_with_budget(chat_id, err_msg, task_id=failed_task_id)
|
||||
send_with_budget(
|
||||
chat_id,
|
||||
err_msg,
|
||||
task_id=failed_task_id,
|
||||
progress_meta={"task_terminal_status": "failed"},
|
||||
)
|
||||
except Exception:
|
||||
log.debug("Suppressed exception", exc_info=True)
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,31 @@ def test_chat_history_preserves_subagent_lane_group_metadata(tmp_path):
|
|||
assert rec["task_group_id"] == "group1"
|
||||
|
||||
|
||||
def test_chat_history_replays_typed_direct_error_terminal_status(tmp_path):
|
||||
logs = tmp_path / "logs"
|
||||
logs.mkdir()
|
||||
(logs / "chat.jsonl").write_text(
|
||||
json.dumps({
|
||||
"ts": "2026-08-27T00:00:00Z",
|
||||
"direction": "out",
|
||||
"chat_id": 1,
|
||||
"user_id": 7,
|
||||
"text": "error",
|
||||
"task_id": "failed-task",
|
||||
"task_terminal_status": "failed",
|
||||
}) + "\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
(logs / "progress.jsonl").write_text("", encoding="utf-8")
|
||||
|
||||
endpoint = make_chat_history_endpoint(tmp_path)
|
||||
response = asyncio.run(endpoint(SimpleNamespace(query_params={"limit": "10"})))
|
||||
payload = json.loads(response.body.decode("utf-8"))["messages"]
|
||||
|
||||
rec = next(item for item in payload if item.get("task_id") == "failed-task")
|
||||
assert rec["task_terminal_status"] == "failed"
|
||||
|
||||
|
||||
def test_chat_history_replays_delivered_document_row(tmp_path):
|
||||
"""A persisted document chat row is replayed as a msg_type=document record so
|
||||
the frontend rebuilds the file bubble on reload from the durable URL."""
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ def test_run_chat_task_unregisters_and_keys_error_final_when_agent_raises(tmp_pa
|
|||
args, kwargs = sent[0]
|
||||
assert args[0] == 5
|
||||
assert kwargs.get("task_id") == str(agent.task["id"])
|
||||
assert kwargs.get("progress_meta") == {"task_terminal_status": "failed"}
|
||||
# The failed turn re-announces the activity<->client_message_id link right
|
||||
# before the keyed final, so the client retires the `Sending...` submission
|
||||
# even when the start announce never reached it.
|
||||
|
|
|
|||
|
|
@ -55,6 +55,38 @@ def test_plan_reference_uses_shared_best_effort_log_event_seam(monkeypatch):
|
|||
}
|
||||
|
||||
|
||||
def test_plan_reference_defaults_unbound_context_to_main_chat(monkeypatch):
|
||||
events: queue.Queue = queue.Queue()
|
||||
ctx = SimpleNamespace(event_queue=events)
|
||||
state = {"current_attempt": {"fingerprint": "review-fingerprint"}, "waves": []}
|
||||
calls = []
|
||||
|
||||
monkeypatch.setattr(
|
||||
plan_review_references,
|
||||
"emit_log_event",
|
||||
lambda _queue, payload, **_kwargs: calls.append(payload),
|
||||
)
|
||||
plan_review_references._emit_plan_review_reference(ctx, "task-1", state)
|
||||
|
||||
assert calls[0]["chat_id"] == 1
|
||||
|
||||
|
||||
def test_plan_reference_preserves_explicit_panel_chat_zero(monkeypatch):
|
||||
events: queue.Queue = queue.Queue()
|
||||
ctx = SimpleNamespace(event_queue=events, current_chat_id=0)
|
||||
state = {"current_attempt": {"fingerprint": "review-fingerprint"}, "waves": []}
|
||||
calls = []
|
||||
|
||||
monkeypatch.setattr(
|
||||
plan_review_references,
|
||||
"emit_log_event",
|
||||
lambda _queue, payload, **_kwargs: calls.append(payload),
|
||||
)
|
||||
plan_review_references._emit_plan_review_reference(ctx, "task-1", state)
|
||||
|
||||
assert calls[0]["chat_id"] == 0
|
||||
|
||||
|
||||
def test_attempt_helper_publishes_immediately_after_the_canonical_write(monkeypatch):
|
||||
ctx = SimpleNamespace(event_queue=queue.Queue())
|
||||
calls = []
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue