mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-07 23:42:21 +02:00
fix: close Wave 1.1 completion-gate audit findings
- Headless consumers (task scheduler, background follow-up) now treat a completion-gate final_response as the authoritative answer instead of collecting deltas only. A gated replacement no longer leaves scheduled output empty, which used to trigger an extra, ungated grace-summary model call. - The scheduler closes the agent stream with contextlib.aclosing, so the approval-pause break unwinds the gate's journal and teacher-takeover context in its own task. Chained runs no longer inherit a stale parent_run_id, and later finalization no longer raises ContextVar reset errors. - On provider error, the completion gate applies the live answer's statement filter to persisted round_texts. Diagnostics and the failure note survive; claims rejected by the gate cannot reappear on reload.
This commit is contained in:
@@ -42,6 +42,7 @@ async def _drain_agent(sess, messages):
|
||||
saves, so the frontend rebuilds them as standard agent-thread tool cards."""
|
||||
from src.agent_loop import stream_agent_loop
|
||||
full = ""
|
||||
final_replaced = False
|
||||
tool_events = []
|
||||
round_num = 1
|
||||
async for chunk in stream_agent_loop(
|
||||
@@ -68,7 +69,17 @@ async def _drain_agent(sess, messages):
|
||||
if isinstance(delta, str):
|
||||
if d.get("thinking"):
|
||||
continue
|
||||
if final_replaced:
|
||||
# A later answer supersedes the replacement, as the
|
||||
# completion gate treats it.
|
||||
full = ""
|
||||
final_replaced = False
|
||||
full += delta
|
||||
elif d.get("type") == "final_response":
|
||||
# The completion gate may present its sanitized answer as one
|
||||
# replacement instead of deltas.
|
||||
full = str(d.get("content") or "")
|
||||
final_replaced = True
|
||||
elif d.get("type") == "agent_step":
|
||||
round_num = d.get("round", round_num)
|
||||
elif d.get("type") == "tool_output":
|
||||
|
||||
Reference in New Issue
Block a user