File size: 7,565 Bytes
85dc375
 
1bde207
85dc375
 
 
1bde207
85dc375
1bde207
 
 
85dc375
 
 
 
 
 
 
 
1bde207
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4567e32
1bde207
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85dc375
1bde207
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65aaea6
85dc375
 
 
 
65aaea6
 
 
 
 
 
 
1bde207
65aaea6
 
1bde207
65aaea6
 
1bde207
65aaea6
 
 
 
 
 
 
 
1bde207
65aaea6
 
1bde207
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65aaea6
1bde207
 
65aaea6
1bde207
 
85dc375
1bde207
 
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
import streamlit as st
import asyncio
import time
from google.adk.sessions import InMemorySessionService
from google.adk.runners import Runner
from google.genai import types
from agent import root_agent  # ← your agent file

# ────────────────────────────────────────────────
# CONFIG
# ────────────────────────────────────────────────
APP_NAME = "leave_policy_app"
session_service = InMemorySessionService()
runner = Runner(
    agent=root_agent,
    app_name=APP_NAME,
    session_service=session_service,
)

# ────────────────────────────────────────────────
# PAGE CONFIG + BASIC STYLING
# ────────────────────────────────────────────────
st.set_page_config(
    page_title="Leave Policy Assistant",
    page_icon="πŸ€–",
    layout="wide",
    initial_sidebar_state="expanded",
)

# Minimal modern styling (safe for 2025+ Streamlit)
st.markdown("""
    <style>
        .stChatMessage {
            margin-bottom: 1.1rem !important;
            border-radius: 16px !important;
        }
        .stChatInput > div > div {
            border-radius: 24px !important;
            padding: 0.5rem 1rem;
        }
    </style>
""", unsafe_allow_html=True)

# ────────────────────────────────────────────────
# SIDEBAR
# ────────────────────────────────────────────────
with st.sidebar:
    st.title("πŸ€– Leave Assistant")
    st.markdown("Ask about leave policy, entitlement, approval, holidays, etc.")
    if "user_id" in st.session_state and st.session_state.user_id:
        st.info(f"**You are:** {st.session_state.user_id}")
    if st.button("Clear conversation", use_container_width=True):
        st.session_state.messages = []
        st.rerun()

# ────────────────────────────────────────────────
# SESSION STATE INIT
# ────────────────────────────────────────────────
defaults = {
    "user_id": "",
    "chat_started": False,
    "messages": [],
}
for key, value in defaults.items():
    if key not in st.session_state:
        st.session_state[key] = value

# ────────────────────────────────────────────────
# LOGIN SCREEN
# ────────────────────────────────────────────────
if not st.session_state.chat_started:
    st.title("Welcome to Leave Policy Assistant")
    st.markdown("Your AI helper for all leave-related questions")

    with st.form("start_form", clear_on_submit=False):
        user_id_input = st.text_input(
            "Enter your name or Employee ID",
            value=st.session_state.user_id,
            placeholder="e.g. Vishal123 or Vishal Patel",
            key="user_id_input"
        )
        if st.form_submit_button("Start Chatting", type="primary", use_container_width=True):
            cleaned = user_id_input.strip()
            if cleaned:
                st.session_state.user_id = cleaned
                st.session_state.chat_started = True
                # Welcome message from bot
                st.session_state.messages.append({
                    "role": "assistant",
                    "content": f"Hi **{cleaned}**! πŸ‘‹ I'm your leave policy assistant.\nHow may I assist you today?"
                })
                st.rerun()
            else:
                st.error("Please enter a valid name or Employee ID")

else:
    # ────────────────────────────────────────────────
    # MAIN CHAT INTERFACE
    # ────────────────────────────────────────────────
    user_id = st.session_state.user_id
    session_id = f"{user_id}_session_{int(time.time())}"  # optional: prevent collision

    # Show history
    for msg in st.session_state.messages:
        role = "user" if msg["role"] == "user" else "assistant"
        avatar = "πŸ‘€" if role == "user" else "πŸ€–"

        with st.chat_message(role, avatar=avatar):
            st.markdown(msg["content"])

    # Input
    user_input = st.chat_input("Ask anything about leave policies…")

    if user_input:
        # Append & display user message immediately
        st.session_state.messages.append({"role": "user", "content": user_input})
        with st.chat_message("user", avatar="πŸ‘€"):
            st.markdown(user_input)

        # Assistant thinking placeholder
        with st.chat_message("assistant", avatar="πŸ€–"):
            placeholder = st.empty()
            placeholder.markdown("β–‹ Thinking…")

        # ── Async agent logic ───────────────────────────────────
        async def run_agent():
            try:
                # Get or create session
                session = await session_service.get_session(
                    app_name=APP_NAME,
                    user_id=user_id,
                    session_id=session_id,
                )
                if not session:
                    await session_service.create_session(
                        app_name=APP_NAME,
                        user_id=user_id,
                        session_id=session_id,
                    )

                # Prepare message
                user_content = types.Content(
                    role="user",
                    parts=[types.Part.from_text(text=user_input)],
                )

                response_text = ""

                async for event in runner.run_async(
                    user_id=user_id,
                    session_id=session_id,
                    new_message=user_content,
                ):
                    if event.is_final_response():
                        if event.content and event.content.parts:
                            response_text = event.content.parts[0].text
                        break

                return response_text or "(No response generated)"

            except Exception as exc:
                return f"**Error occurred:** {str(exc)}"

        # Execute async function in sync Streamlit context
        try:
            response = asyncio.run(run_agent())
        except RuntimeError as e:
            # Common in some environments when event loop is already running
            loop = asyncio.get_event_loop()
            if loop.is_running():
                response = loop.run_until_complete(run_agent())
            else:
                response = f"Async loop error: {str(e)}"

        # Replace placeholder with real answer
        placeholder.markdown(response)

        # Save to history
        st.session_state.messages.append({"role": "assistant", "content": response})

        # Refresh UI
        st.rerun()