File size: 4,398 Bytes
faf123b
 
b44478d
 
 
 
faf123b
 
 
 
b44478d
 
 
 
 
 
 
 
faf123b
 
 
b44478d
16c61ea
cfea2d4
b44478d
 
 
 
 
 
 
 
 
 
 
 
70e1667
 
b44478d
 
ea7a6ee
 
faf123b
 
 
 
 
 
 
 
5a2f067
faf123b
 
5a2f067
faf123b
 
 
 
 
d9d2959
 
b44478d
 
 
 
 
 
 
 
 
 
faf123b
b44478d
 
d9d2959
 
 
faf123b
d9d2959
faf123b
 
 
 
 
 
 
 
 
b44478d
faf123b
 
 
16c61ea
faf123b
 
 
 
 
 
 
 
ea7a6ee
faf123b
 
 
b44478d
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
from google import genai
from google.genai import types
import traceback
from ..config import db, get_user_keys

class AiModalEngine:
    @staticmethod
    def _get_client(api_key):
        return genai.Client(api_key=api_key)

    @staticmethod
    def initialize_firebase_session(uid, context):
        try:
            keys = get_user_keys(uid)
            api_key = keys.get('gemini_key')
            if not api_key: 
                return "Error: No API Key found in Settings."

            client = AiModalEngine._get_client(api_key)
            
            # Parsona
            instruction = f"""
            PERSONA:
            You are the QuantVAT AI Trading Journal Auditor, a senior Risk Manager and Trading Psychologist with 50 years trading experience like a Market Wizard. 
            Speak with veteran authority. Tone is blunt but constructive.

            MANDATE:
            1. Analyze the 'WHY' behind execution based on the provided logs.
            2. STRUCTURE: 
               - ## ๐Ÿ“Š OVERVIEW: 2-sentence performance reality check.
               - ## ๐Ÿšฉ RED FLAGS: Top 2 execution errors (FOMO, sizing, fear, etc).
               - ## ๐Ÿ’ก THE REMEDY: One specific, actionable rule for the next session.
            3. FORMAT: Use bold text for emphasis. 
            4. NO TABLES: Use bullet points only.
            5. INTERACTION: End with a provocative question about a specific trade.

            TRADING LEDGER (CSV FORMAT):
            {context}
            """

            prompt = "Analyze my execution performance based on the CSV data above. End with: 'I have analyzed your data. Ready for audit.'"
            
            response = client.models.generate_content(
                model='gemini-3-flash-preview', 
                contents=prompt,
                config=types.GenerateContentConfig(
                    system_instruction=instruction
                )
            )
            
            history = [
                {"role": "user", "parts": [{"text": prompt}]}, 
                {"role": "model", "parts": [{"text": response.text}]}
            ]
            
            db.collection('users').document(uid).set({
                "ai_history": history,
                "ai_context": context
            }, merge=True)
            
            return response.text
        except Exception as e:
            print(f"AI Init Error: {traceback.format_exc()}")
            return f"System Error: {str(e)}"

    @staticmethod
    def continue_firebase_chat(uid, prompt):
        try:
            user_doc = db.collection('users').document(uid).get()
            data = user_doc.to_dict() if user_doc.exists else {}
            history = data.get("ai_history", [])
            context = data.get("ai_context", "") 
            
            api_key = get_user_keys(uid).get('gemini_key')
            if not api_key: 
                return "Error: API Key missing."

            client = AiModalEngine._get_client(api_key)
            
            # Robust mapping
            contents = []
            for h in history:
                p = h['parts'][0]
                text_content = p['text'] if isinstance(p, dict) else str(p)
                contents.append(types.Content(
                    role=h['role'], 
                    parts=[types.Part.from_text(text=text_content)]
                ))
            
            contents.append(types.Content(role="user", parts=[types.Part.from_text(text=prompt)]))

            # Re-injects Persona
            instruction = f"PERSONA: QuantVAT AI Trading Journal Auditor. Senior Risk Manager.\nDATA:\n{context}"

            response = client.models.generate_content(
                model='gemini-3-flash-preview',
                contents=contents,
                config=types.GenerateContentConfig(
                    system_instruction=instruction
                )
            )
            
            # Append new turn and sync to Firestore 
            history.append({"role": "user", "parts": [{"text": prompt}]})
            history.append({"role": "model", "parts": [{"text": response.text}]})
            db.collection('users').document(uid).set({"ai_history": history}, merge=True)
            
            return response.text
        except Exception as e:
            print(f"AI Chat Error: {traceback.format_exc()}")
            return f"Auditor Error: {str(e)}"