Code Walkthrough
This document provides a detailed walkthrough of how the code works, with diagrams showing the relationships between different components.
1. Entry Points and Main Flow
graph TD
subgraph "Frontend Entry"
USER[User Input]
CHAT[ChatContainer.tsx]
INPUT[UserInput.tsx]
end
subgraph "API Call"
CTX[ChatContext.tsx]
API[api.ts:getAIResponse]
HTTP[HTTP POST]
end
subgraph "Backend Entry"
ROUTE[chat.py:send_message]
AGENT[financial_agent.py]
RESP[Response]
end
USER --> INPUT
INPUT --> CHAT
CHAT --> CTX
CTX --> API
API --> HTTP
HTTP --> ROUTE
ROUTE --> AGENT
AGENT --> RESP
RESP --> CTX
style USER fill:#fbbf24
style CTX fill:#818cf8
style AGENT fill:#4ade80
2. Backend Code Structure
classDiagram
class FinancialAgentSystem {
-conversation_state: ConversationState
-yfinance_server: YFinanceMCPServer
-web_search_server: WebSearchMCPServer
-llm_client: Gemini
+process_question(question, history)
}
class MCPServer {
-name: string
-tools: dict
+register_tool(name, func, description)
+call_tool(tool_name, kwargs)
}
class YFinanceMCPServer {
-alpha_vantage_ts: TimeSeries
-alpha_vantage_fd: FundamentalData
+_get_stock_price(ticker)
+_get_historical_data(ticker, period)
+_get_portfolio_analysis(symbols, weights)
+_get_company_info(ticker)
}
class WebSearchMCPServer {
-client: Gemini
+_search(query, focus)
+_get_news(topic, timeframe)
}
class ConversationState {
-messages: list
-context: dict
+add_message(role, content, metadata)
+get_context_summary()
}
FinancialAgentSystem --> ConversationState
FinancialAgentSystem --> YFinanceMCPServer
FinancialAgentSystem --> WebSearchMCPServer
YFinanceMCPServer --|> MCPServer
WebSearchMCPServer --|> MCPServer
3. Frontend Component Hierarchy
graph TD
subgraph "App Structure"
APP[App.tsx]
PROVIDER[ChatProvider]
HEADER[Header.tsx]
SIDEBAR[Sidebar.tsx]
MAIN[Main Content]
end
subgraph "Chat Components"
CONTAINER[ChatContainer.tsx]
MESSAGE[Message.tsx]
INPUT[UserInput.tsx]
end
subgraph "Tool Components"
STOCK[StockCard.tsx]
NEWS[NewsCard.tsx]
end
APP --> PROVIDER
PROVIDER --> HEADER
PROVIDER --> SIDEBAR
PROVIDER --> MAIN
MAIN --> CONTAINER
CONTAINER --> MESSAGE
CONTAINER --> INPUT
MESSAGE --> STOCK
MESSAGE --> NEWS
style APP fill:#61dafb
style PROVIDER fill:#818cf8
style MESSAGE fill:#4ade80
4. API Endpoint Flow
# Backend: app/api/chat.py
@router.post("/", response_model=ChatResponse)
async def send_message(request: ChatRequest):
"""
1. Check for Gemini API key
2. Get conversation history from DB
3. Process with financial_agent
4. Format response for frontend
5. Save to database
6. Return ChatResponse
"""
flowchart TD
REQ[Request: ChatRequest]
CHECK{Gemini API?}
HIST[Get History from DB]
PROCESS[financial_agent.process_question]
FORMAT[Format Response]
SAVE[Save to DB]
RETURN[Return ChatResponse]
REQ --> CHECK
CHECK -->|Yes| HIST
CHECK -->|No| MOCK[Use Mock Service]
HIST --> PROCESS
MOCK --> FORMAT
PROCESS --> FORMAT
FORMAT --> SAVE
SAVE --> RETURN
style REQ fill:#fbbf24
style PROCESS fill:#818cf8
style RETURN fill:#4ade80
5. Financial Agent Processing Steps
stateDiagram-v2
[*] --> AddUserMessage
AddUserMessage --> GetContext
note right of GetContext: Last 6 messages
GetContext --> CreatePrompt
note right of CreatePrompt: Include tools & context
CreatePrompt --> GeminiPlan
note left of GeminiPlan: AI creates JSON plan
GeminiPlan --> ExecutePlan
state ExecutePlan {
[*] --> ReadStep
ReadStep --> CheckAgent
CheckAgent --> GatherData: data_gatherer
CheckAgent --> Analyze: analyzer
state GatherData {
[*] --> CallTool
CallTool --> RouteServer
RouteServer --> Execute
Execute --> StoreResult
StoreResult --> [*]
}
GatherData --> ReadStep: Next step
Analyze --> [*]: Done
}
ExecutePlan --> FormatResponse
FormatResponse --> [*]
6. Data Source Selection Logic
flowchart TD
START[Start: Get ticker]
TRY1[Try yfinance.history]
CHECK1{Has data?}
TRY2[Try yf.download]
CHECK2{Has data?}
TRY3[Try Alpha Vantage]
CHECK3{Success?}
MOCK[Use Mock Data]
CHECK4{Known ticker?}
SUCCESS[Return data]
ERROR[Return error]
START --> TRY1
TRY1 --> CHECK1
CHECK1 -->|Yes| SUCCESS
CHECK1 -->|No| TRY2
TRY2 --> CHECK2
CHECK2 -->|Yes| SUCCESS
CHECK2 -->|No| TRY3
TRY3 --> CHECK3
CHECK3 -->|Yes| SUCCESS
CHECK3 -->|No| MOCK
MOCK --> CHECK4
CHECK4 -->|Yes| SUCCESS
CHECK4 -->|No| ERROR
style START fill:#fbbf24
style SUCCESS fill:#4ade80
style ERROR fill:#ef4444
7. Frontend State Management
graph TD
subgraph ChatState ["ChatContext State"]
STATE[State]
STATE --> MESSAGES[messages: Message Array]
STATE --> LOADING[isLoading: boolean]
end
subgraph Actions ["Actions"]
SEND[sendMessage]
CLEAR[clearChat]
end
subgraph Effects ["Effects"]
SAVE[Save to localStorage]
LOAD[Load from localStorage]
end
SEND --> API[Call API]
API --> UPDATE[Update messages]
UPDATE --> SAVE
CLEAR --> RESET[Reset state]
RESET --> SAVE
LOAD --> STATE
style STATE fill:#818cf8
style SEND fill:#4ade80
style API fill:#fbbf24
8. Tool Result Processing
graph LR
subgraph "Gathered Data"
RAW[Raw Results Dict]
RAW --> CHECK{Status: success?}
end
subgraph "Type Detection"
CHECK -->|Yes| DETECT[Detect tool type]
DETECT --> PRICE{Has price?}
DETECT --> NEWS{Has search/news?}
DETECT --> PORT{Has portfolio?}
end
subgraph "Tool Creation"
PRICE -->|Yes| STOCK[Create Stock Tool]
NEWS -->|Yes| NEWST[Create News Tool]
PORT -->|Yes| EARN[Create Earnings Tool]
end
subgraph "Output"
STOCK --> ARRAY[tools array]
NEWST --> ARRAY
EARN --> ARRAY
end
style RAW fill:#fbbf24
style ARRAY fill:#4ade80
9. Complete Example: "What's Apple stock price?"
sequenceDiagram
participant U as User
participant UI as UserInput.tsx
participant CTX as ChatContext
participant API as api.ts
participant BE as Backend
participant FA as FinancialAgent
participant G1 as Gemini (Plan)
participant YF as YFinance
participant G2 as Gemini (Analysis)
U->>UI: Types "What's Apple stock price?"
UI->>CTX: sendMessage()
CTX->>API: getAIResponse()
API->>BE: POST /api/chat/
BE->>FA: process_question()
FA->>G1: Create plan for question
G1-->>FA: {steps: [{tool: "get_stock_price", params: {ticker: "AAPL"}}]}
FA->>YF: get_stock_price("AAPL")
YF-->>FA: {price: 189.50, change: 2.35, ...}
FA->>G2: Analyze data and create response
G2-->>FA: "Apple (AAPL) is currently trading at $189.50..."
FA-->>BE: {content: "...", tools: [{type: "price", data: {...}}]}
BE-->>API: ChatResponse
API-->>CTX: Message object
CTX-->>UI: Update UI with message
Note over UI: Displays message with StockCard
Key Code Patterns
1. Async/Await Pattern
async def process_question(self, question: str):
# All I/O operations are async
result = await self.yfinance_server.call_tool(...)
2. Error Handling Pattern
3. State Management Pattern
const [messages, setMessages] = useState<Message[]>([]);
// Immutable updates
setMessages(prev => [...prev, newMessage]);