Files
AI-Trader/agent/context_injector.py
Bill 019c84fca8 refactor: migrate trade tools from file-based to SQLite position storage
Complete rewrite of position management in MCP trade tools:

**Trade Tools (agent_tools/tool_trade.py)**
- Replace file-based position.jsonl reads with SQLite queries
- Add get_current_position_from_db() to query positions and holdings tables
- Rewrite buy() and sell() to write directly to database
- Calculate portfolio value and P&L metrics in tools
- Accept job_id and session_id parameters via ContextInjector
- Return errors with proper context for debugging
- Use deployment-aware database path resolution

**Context Injection (agent/context_injector.py)**
- Add job_id and session_id to constructor
- Inject job_id and session_id into buy/sell tool calls
- Support optional parameters (None in standalone mode)

**BaseAgent (agent/base_agent/base_agent.py)**
- Read JOB_ID from runtime config
- Pass job_id to ContextInjector during initialization
- Enable automatic context injection for API mode

**ModelDayExecutor (api/model_day_executor.py)**
- Add _initialize_starting_position() method
- Create initial position record before agent runs
- Load initial_cash from config
- Update context_injector.session_id after session creation
- Link positions to sessions automatically

**Architecture Changes:**
- Eliminates file-based position tracking entirely
- Single source of truth: SQLite database
- Positions automatically linked to trading sessions
- Concurrent execution safe (no file system conflicts)
- Deployment mode aware (prod vs dev databases)

This completes the migration to database-only position storage.
File-based position.jsonl is no longer used or created.

Fixes context injection errors in concurrent simulations.
2025-11-02 21:36:57 -05:00

67 lines
2.4 KiB
Python

"""
Tool interceptor for injecting runtime context into MCP tool calls.
This interceptor automatically injects `signature` and `today_date` parameters
into buy/sell tool calls to support concurrent multi-model simulations.
"""
from typing import Any, Callable, Awaitable
class ContextInjector:
"""
Intercepts tool calls to inject runtime context (signature, today_date).
Usage:
interceptor = ContextInjector(signature="gpt-5", today_date="2025-10-01")
client = MultiServerMCPClient(config, tool_interceptors=[interceptor])
"""
def __init__(self, signature: str, today_date: str, job_id: str = None, session_id: int = None):
"""
Initialize context injector.
Args:
signature: Model signature to inject
today_date: Trading date to inject
job_id: Job UUID to inject (optional)
session_id: Trading session ID to inject (optional, updated during execution)
"""
self.signature = signature
self.today_date = today_date
self.job_id = job_id
self.session_id = session_id
async def __call__(
self,
request: Any, # MCPToolCallRequest
handler: Callable[[Any], Awaitable[Any]]
) -> Any: # MCPToolCallResult
"""
Intercept tool call and inject context parameters.
Args:
request: Tool call request containing name and arguments
handler: Async callable to execute the actual tool
Returns:
Result from handler after injecting context
"""
# Inject context parameters 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
if "job_id" not in request.args and self.job_id:
request.args["job_id"] = self.job_id
if "session_id" not in request.args and self.session_id:
request.args["session_id"] = self.session_id
# Debug logging
print(f"[ContextInjector] Tool: {request.name}, Args after injection: {request.args}")
# Call the actual tool handler
return await handler(request)