Compare commits

..

4 Commits

Author SHA1 Message Date
8521f685c7 fix: improve error handling in buy/sell functions
Add proper exception handling around get_latest_position() calls in both
buy() and sell() functions. Previously, exceptions were caught but code
continued execution with undefined variables, causing "variable referenced
before assignment" errors.

Now returns error dict with context when position lookup fails.

Related to context injection implementation for concurrent simulations.
2025-11-02 20:38:55 -05:00
bf12e981fe debug: add logging to trace parameter injection 2025-11-02 20:29:35 -05:00
a16bac5d08 fix: use 'args' instead of 'arguments' in MCPToolCallRequest
MCPToolCallRequest has 'args' attribute, not 'arguments'. Fixed
attribute name to match the actual API.
2025-11-02 20:21:43 -05:00
81b92e293a fix: make ContextInjector async to match ToolCallInterceptor protocol
The interceptor __call__ method must be async and follow the proper
signature: async __call__(request, handler) -> result

Previous implementation was synchronous and had wrong signature, causing
'object function can't be used in await expression' error.
2025-11-02 20:11:20 -05:00
2 changed files with 28 additions and 17 deletions

View File

@@ -5,7 +5,7 @@ This interceptor automatically injects `signature` and `today_date` parameters
into buy/sell tool calls to support concurrent multi-model simulations.
"""
from typing import Any, Dict
from typing import Any, Callable, Awaitable
class ContextInjector:
@@ -28,23 +28,31 @@ class ContextInjector:
self.signature = signature
self.today_date = today_date
def __call__(self, tool_name: str, tool_input: Dict[str, Any]) -> Dict[str, Any]:
async def __call__(
self,
request: Any, # MCPToolCallRequest
handler: Callable[[Any], Awaitable[Any]]
) -> Any: # MCPToolCallResult
"""
Intercept tool call and inject context parameters.
Args:
tool_name: Name of the tool being called
tool_input: Original tool input parameters
request: Tool call request containing name and arguments
handler: Async callable to execute the actual tool
Returns:
Modified tool input with injected context
Result from handler after injecting context
"""
# Only inject for trade tools (buy/sell)
if tool_name in ["buy", "sell"]:
# Inject signature and today_date if not already provided
if "signature" not in tool_input:
tool_input["signature"] = self.signature
if "today_date" not in tool_input:
tool_input["today_date"] = self.today_date
# Inject signature and today_date for trade tools
if request.name in ["buy", "sell"]:
# Add signature and today_date to args if not present
if "signature" not in request.args:
request.args["signature"] = self.signature
if "today_date" not in request.args:
request.args["today_date"] = self.today_date
return tool_input
# Debug logging
print(f"[ContextInjector] Tool: {request.name}, Args after injection: {request.args}")
# Call the actual tool handler
return await handler(request)

View File

@@ -44,8 +44,10 @@ def buy(symbol: str, amount: int, signature: str = None, today_date: str = None)
"""
# Step 1: Get environment variables and basic information
# Get signature (model name) from parameter or fallback to config/env
print(f"[buy] Received signature parameter: {signature}")
if signature is None:
signature = get_config_value("SIGNATURE")
print(f"[buy] Signature from config: {signature}")
if signature is None:
raise ValueError("SIGNATURE not provided and environment variable is not set")
@@ -59,9 +61,7 @@ def buy(symbol: str, amount: int, signature: str = None, today_date: str = None)
try:
current_position, current_action_id = get_latest_position(today_date, signature)
except Exception as e:
print(e)
print(current_position, current_action_id)
print(today_date, signature)
return {"error": f"Failed to get position: {str(e)}", "signature": signature, "date": today_date}
# Step 3: Get stock opening price for the day
# Use get_open_prices function to get the opening price of specified stock for the day
# If stock symbol does not exist or price data is missing, KeyError exception will be raised
@@ -151,7 +151,10 @@ def sell(symbol: str, amount: int, signature: str = None, today_date: str = None
# Step 2: Get current latest position and operation ID
# get_latest_position returns two values: position dictionary and current maximum operation ID
# This ID is used to ensure each operation has a unique identifier
current_position, current_action_id = get_latest_position(today_date, signature)
try:
current_position, current_action_id = get_latest_position(today_date, signature)
except Exception as e:
return {"error": f"Failed to get position: {str(e)}", "signature": signature, "date": today_date}
# Step 3: Get stock opening price for the day
# Use get_open_prices function to get the opening price of specified stock for the day