mirror of
https://github.com/VectifyAI/PageIndex.git
synced 2026-07-15 21:11:05 +02:00
- 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
47 lines
1.6 KiB
Python
47 lines
1.6 KiB
Python
from pageindex.agent import AgentRunner, OPEN_SYSTEM_PROMPT, SCOPED_SYSTEM_PROMPT
|
|
from pageindex.backend.protocol import AgentTools
|
|
|
|
|
|
def test_agent_runner_init():
|
|
tools = AgentTools(function_tools=["mock_tool"])
|
|
runner = AgentRunner(tools=tools, model="gpt-4o")
|
|
assert runner._model == "gpt-4o"
|
|
|
|
|
|
def test_open_prompt_has_tool_instructions():
|
|
assert "list_documents" in OPEN_SYSTEM_PROMPT
|
|
assert "get_document_structure" in OPEN_SYSTEM_PROMPT
|
|
assert "get_page_content" in OPEN_SYSTEM_PROMPT
|
|
|
|
|
|
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"
|