96 lines
3.3 KiB
Python
Raw Normal View History

2025-11-04 05:17:27 +01:00
import json
import logging
2025-11-04 08:09:12 +01:00
import urllib.error
import urllib.request
from pr.config import DEFAULT_MAX_TOKENS, DEFAULT_TEMPERATURE
2025-11-04 05:17:27 +01:00
from pr.core.context import auto_slim_messages
2025-11-04 08:09:12 +01:00
logger = logging.getLogger("pr")
2025-11-04 05:17:27 +01:00
2025-11-04 08:10:37 +01:00
def call_api(messages, model, api_url, api_key, use_tools, tools_definition, verbose=False):
2025-11-04 05:17:27 +01:00
try:
messages = auto_slim_messages(messages, verbose=verbose)
logger.debug(f"=== API CALL START ===")
logger.debug(f"Model: {model}")
logger.debug(f"API URL: {api_url}")
logger.debug(f"Use tools: {use_tools}")
logger.debug(f"Message count: {len(messages)}")
headers = {
2025-11-04 08:09:12 +01:00
"Content-Type": "application/json",
2025-11-04 05:17:27 +01:00
}
if api_key:
2025-11-04 08:09:12 +01:00
headers["Authorization"] = f"Bearer {api_key}"
2025-11-04 05:17:27 +01:00
data = {
2025-11-04 08:09:12 +01:00
"model": model,
"messages": messages,
"temperature": DEFAULT_TEMPERATURE,
"max_tokens": DEFAULT_MAX_TOKENS,
2025-11-04 05:17:27 +01:00
}
if "gpt-5" in model:
2025-11-04 08:09:12 +01:00
del data["temperature"]
del data["max_tokens"]
2025-11-04 05:17:27 +01:00
logger.debug("GPT-5 detected: removed temperature and max_tokens")
if use_tools:
2025-11-04 08:09:12 +01:00
data["tools"] = tools_definition
data["tool_choice"] = "auto"
2025-11-04 05:17:27 +01:00
logger.debug(f"Tool calling enabled with {len(tools_definition)} tools")
request_json = json.dumps(data)
logger.debug(f"Request payload size: {len(request_json)} bytes")
req = urllib.request.Request(
2025-11-04 08:09:12 +01:00
api_url, data=request_json.encode("utf-8"), headers=headers, method="POST"
2025-11-04 05:17:27 +01:00
)
logger.debug("Sending HTTP request...")
with urllib.request.urlopen(req) as response:
2025-11-04 08:09:12 +01:00
response_data = response.read().decode("utf-8")
2025-11-04 05:17:27 +01:00
logger.debug(f"Response received: {len(response_data)} bytes")
result = json.loads(response_data)
2025-11-04 08:09:12 +01:00
if "usage" in result:
2025-11-04 05:17:27 +01:00
logger.debug(f"Token usage: {result['usage']}")
2025-11-04 08:09:12 +01:00
if "choices" in result and result["choices"]:
choice = result["choices"][0]
if "message" in choice:
msg = choice["message"]
2025-11-04 05:17:27 +01:00
logger.debug(f"Response role: {msg.get('role', 'N/A')}")
2025-11-04 08:09:12 +01:00
if "content" in msg and msg["content"]:
2025-11-04 08:10:37 +01:00
logger.debug(f"Response content length: {len(msg['content'])} chars")
2025-11-04 08:09:12 +01:00
if "tool_calls" in msg:
2025-11-04 08:10:37 +01:00
logger.debug(f"Response contains {len(msg['tool_calls'])} tool call(s)")
2025-11-04 05:17:27 +01:00
logger.debug("=== API CALL END ===")
return result
except urllib.error.HTTPError as e:
2025-11-04 08:09:12 +01:00
error_body = e.read().decode("utf-8")
2025-11-04 05:17:27 +01:00
logger.error(f"API HTTP Error: {e.code} - {error_body}")
logger.debug("=== API CALL FAILED ===")
return {"error": f"API Error: {e.code}", "message": error_body}
except Exception as e:
logger.error(f"API call failed: {e}")
logger.debug("=== API CALL FAILED ===")
return {"error": str(e)}
2025-11-04 08:09:12 +01:00
2025-11-04 05:17:27 +01:00
def list_models(model_list_url, api_key):
try:
req = urllib.request.Request(model_list_url)
if api_key:
2025-11-04 08:09:12 +01:00
req.add_header("Authorization", f"Bearer {api_key}")
2025-11-04 05:17:27 +01:00
with urllib.request.urlopen(req) as response:
2025-11-04 08:09:12 +01:00
data = json.loads(response.read().decode("utf-8"))
2025-11-04 05:17:27 +01:00
2025-11-04 08:09:12 +01:00
return data.get("data", [])
2025-11-04 05:17:27 +01:00
except Exception as e:
return {"error": str(e)}