feat: portfolio context injection + AI call log viewer
Portfolio context (portfolio_context.py): - get_open_trades_with_moves(): fetches open trades + 1d/5d yfinance price moves - get_portfolio_concentration(): counts by asset_class - build_portfolio_context_block(): formatted prompt block with strict AI instructions (no double positions, flag contradictions, avoid overweight classes) AI call logging: - ai_call_logs table in DB (run_id, call_type, system/user prompt, response, tokens, ms) - _chat() now accepts log_meta dict → saves call to DB non-blocking after each call - suggest and score_batch calls pass run_id + call_type for full traceability auto_cycle.py: - Builds portfolio context before snapshot and both AI calls - Context snapshot now includes portfolio_open_positions key SystemLogs.tsx: - "Contexte IA" tab gains sub-tabs: Contexte / Appels IA - AiCallRow: expandable with 3 panes (user prompt / system prompt / response) shows model, tokens breakdown, duration, call type badge Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
from services.database import get_cycle_runs, get_cycle_run, set_config, get_config, list_cycle_context_snapshots, get_cycle_context_snapshot
|
||||
from services.database import get_cycle_runs, get_cycle_run, set_config, get_config, list_cycle_context_snapshots, get_cycle_context_snapshot, get_ai_call_logs
|
||||
from services.auto_cycle import get_status, trigger_manual, restart_scheduler
|
||||
|
||||
router = APIRouter(prefix="/api/cycle", tags=["cycle"])
|
||||
@@ -100,6 +100,13 @@ def get_context_snapshot(run_id: str):
|
||||
return snap
|
||||
|
||||
|
||||
@router.get("/ai-calls/{run_id}")
|
||||
def get_cycle_ai_calls(run_id: str):
|
||||
"""Return all AI calls logged for a given cycle run_id."""
|
||||
calls = get_ai_call_logs(run_id)
|
||||
return {"run_id": run_id, "calls": calls, "count": len(calls)}
|
||||
|
||||
|
||||
class ReplayRequest(BaseModel):
|
||||
override_notes: Optional[str] = None # optional annotation added to the replay
|
||||
|
||||
|
||||
Reference in New Issue
Block a user