fix: resolve five P1 defects from the SDK review

- AgentRunner.run: offload to a worker-thread event loop when called
  from inside a running loop (Jupyter, FastAPI handlers) — mirrors
  pipeline._run_async; Runner.run_sync raised RuntimeError there.

- SQLiteStorage: create connections with check_same_thread=False so
  close() can actually close connections created by worker threads.
  Each thread still gets its own connection via threading.local; with
  the default True those closes raised ProgrammingError (silently
  swallowed) and leaked every worker connection.

- CloudBackend.query: non-streaming chat completions now use a 300s
  timeout and a single attempt. The default 30s ReadTimeout fired
  before generation finished and the retry loop re-billed the full
  server-side retrieval + generation up to three times. _request gains
  retries/timeout overrides; the exhausted-retry path also no longer
  sleeps before raising.

- MarkdownParser: content before the first heading (abstract/preamble)
  becomes a node instead of being silently dropped and unretrievable;
  a file with no headings at all yields a single document node instead
  of zero nodes (which pushed an empty page list into the pipeline).

- LegacyCloudAPI.is_retrieval_ready: API failures (revoked key, network
  down) now propagate as PageIndexAPIError instead of reading as
  "not ready", which turned polling loops into infinite loops.

Adds regression tests for each fix.

Claude-Session: https://claude.ai/code/session_01Kx5DgKbhK1N8autqXH8SmS
This commit is contained in:
mountain 2026-07-07 10:12:51 +08:00
parent 6a73279c0c
commit 956147d864
10 changed files with 171 additions and 16 deletions

View file

@ -18,3 +18,30 @@ def test_scoped_prompt_omits_list_documents():
assert "list_documents" not in SCOPED_SYSTEM_PROMPT
assert "get_document_structure" in SCOPED_SYSTEM_PROMPT
assert "get_page_content" in SCOPED_SYSTEM_PROMPT
def test_run_works_inside_running_event_loop(monkeypatch):
"""Regression: Runner.run_sync raises RuntimeError under a running loop
(Jupyter/FastAPI); AgentRunner.run must offload to a worker thread."""
import asyncio
agents = __import__("agents")
class FakeResult:
final_output = "ok"
async def fake_run(agent, question):
return FakeResult()
def fail_run_sync(agent, question):
raise AssertionError("run_sync must not be called inside a running loop")
monkeypatch.setattr(agents.Runner, "run", fake_run)
monkeypatch.setattr(agents.Runner, "run_sync", fail_run_sync)
monkeypatch.setattr(agents, "Agent", lambda **kwargs: object())
runner = AgentRunner(tools=AgentTools(function_tools=[]), model="gpt-4o")
async def main():
return runner.run("question") # sync call from inside a running loop
assert asyncio.run(main()) == "ok"