feat: replace synchronous HTTP calls with async client and add background task tracking

This commit is contained in:
2025-11-06 15:44:41 +00:00
parent 99d7ec53d5
commit e018cff131
19 changed files with 531 additions and 1771 deletions
+69 -22
View File
@@ -1,9 +1,13 @@
import asyncio
import asyncio
import json
import logging
import time
from pr.autonomous.detection import is_task_complete
from pr.core.api import call_api
from pr.core.context import truncate_tool_result
from pr.tools.base import get_tools_definition
from pr.ui import Colors, display_tool_call
logger = logging.getLogger("pr")
@@ -35,18 +39,39 @@ def run_autonomous_mode(assistant, task):
logger.debug(f"Messages after context management: {len(assistant.messages)}")
from pr.core.api import call_api
from pr.tools.base import get_tools_definition
try:
# Try to get the current event loop
loop = asyncio.get_running_loop()
# If we're in an event loop, use run_coroutine_threadsafe
import concurrent.futures
response = call_api(
assistant.messages,
assistant.model,
assistant.api_url,
assistant.api_key,
assistant.use_tools,
get_tools_definition(),
verbose=assistant.verbose,
)
with concurrent.futures.ThreadPoolExecutor() as executor:
future = asyncio.run_coroutine_threadsafe(
call_api(
assistant.messages,
assistant.model,
assistant.api_url,
assistant.api_key,
assistant.use_tools,
get_tools_definition(),
verbose=assistant.verbose,
),
loop,
)
response = future.result()
except RuntimeError:
# No event loop running, use asyncio.run
response = asyncio.run(
call_api(
assistant.messages,
assistant.model,
assistant.api_url,
assistant.api_key,
assistant.use_tools,
get_tools_definition(),
verbose=assistant.verbose,
)
)
if "error" in response:
logger.error(f"API error in autonomous mode: {response['error']}")
@@ -118,18 +143,40 @@ def process_response_autonomous(assistant, response):
for result in tool_results:
assistant.messages.append(result)
from pr.core.api import call_api
from pr.tools.base import get_tools_definition
follow_up = call_api(
assistant.messages,
assistant.model,
assistant.api_url,
assistant.api_key,
assistant.use_tools,
get_tools_definition(),
verbose=assistant.verbose,
)
try:
# Try to get the current event loop
loop = asyncio.get_running_loop()
# If we're in an event loop, use run_coroutine_threadsafe
import concurrent.futures
with concurrent.futures.ThreadPoolExecutor() as executor:
future = asyncio.run_coroutine_threadsafe(
call_api(
assistant.messages,
assistant.model,
assistant.api_url,
assistant.api_key,
assistant.use_tools,
get_tools_definition(),
verbose=assistant.verbose,
),
loop,
)
follow_up = future.result()
except RuntimeError:
# No event loop running, use asyncio.run
follow_up = asyncio.run(
call_api(
assistant.messages,
assistant.model,
assistant.api_url,
assistant.api_key,
assistant.use_tools,
get_tools_definition(),
verbose=assistant.verbose,
)
)
return process_response_autonomous(assistant, follow_up)
content = message.get("content", "")