Studio: address Deep Research lifecycle review

This commit is contained in:
alkinun 2026-07-18 12:54:38 +03:00
commit 7113d85245
5 changed files with 44 additions and 1 deletions

View file

@ -385,6 +385,8 @@ class ResearchSupervisor:
self._stopping.set()
try:
if self._task is not None:
for cancel_event in self._cancel_events.values():
cancel_event.set()
self._task.cancel()
try:
await self._task

View file

@ -865,6 +865,7 @@ def reset_execution_steps(run_id: str, worker_id: str | None = None) -> bool:
conn.commit()
return False
conn.execute("DELETE FROM research_plan_steps WHERE run_id = ?", (run_id,))
conn.execute("DELETE FROM research_sources WHERE run_id = ?", (run_id,))
conn.commit()
return True
except Exception:

View file

@ -448,6 +448,43 @@ def test_recovery_releases_expired_leases(research_home, status):
assert claimed["status"] == expected
def test_execution_reset_clears_steps_and_sources(research_home):
_create()
plan = research_db.set_plan("run-1", _plan())
research_db.approve("run-1", plan["planRevision"], plan["planHash"])
research_db.claim_next("worker-1")
research_db.upsert_execution_step(
"run-1", 0, "Old step", "old query", "completed", worker_id = "worker-1"
)
research_db.upsert_source("run-1", 0, "https://old.example", "Old", "Stale", "worker-1")
assert research_db.reset_execution_steps("run-1", "worker-1") is True
run = research_db.get_run("run-1")
assert run["steps"] == []
assert run["sources"] == []
def test_supervisor_stop_signals_tool_cancellation_before_task_cancelled(research_home):
from core.research_runs import ResearchSupervisor
async def scenario():
supervisor = ResearchSupervisor(SimpleNamespace(state = SimpleNamespace()))
cancel_event = supervisor._cancel_event("run-1")
async def active_run():
try:
await asyncio.Event().wait()
except asyncio.CancelledError:
assert cancel_event.is_set()
raise
supervisor._task = asyncio.create_task(active_run())
await asyncio.sleep(0)
await supervisor.stop()
assert cancel_event.is_set()
asyncio.run(scenario())
def test_sources_are_normalized_by_url(research_home):
_create()
research_db.upsert_source("run-1", 0, "https://example.com/a", "Old", "one")

View file

@ -2036,7 +2036,9 @@ export function createOpenAIStreamAdapter(
autoinject_min_score: runtime.ragAutoInjectMinScore,
}
: {
thread_id: resolvedThreadId,
...(runtime.ragEnabled
? { thread_id: resolvedThreadId }
: {}),
...(researchProjectId
? { project_id: researchProjectId }
: {}),

View file

@ -59,6 +59,7 @@ def test_research_mode_is_single_chat_and_detaches_without_cancel() -> None:
assert "signal: researchFollowController.signal" in adapter
assert "beginExternalResearchFollow(" in adapter
assert "ragScope" in adapter
assert "runtime.ragEnabled\n ? { thread_id: resolvedThreadId }" in adapter
create_block = adapter.split("createdRun = await createResearchRun({", 1)[1].split("});", 1)[0]
assert "modelId:" not in create_block
assert "prompt," not in create_block