"""AutoStream AI Sales Agent — Streamlit UI."""
from __future__ import annotations
import streamlit as st
from dotenv import load_dotenv
load_dotenv()
from langchain_core.messages import HumanMessage, AIMessage
from agent.graph import get_app
from agent.state import AgentState
st.set_page_config(
page_title="AutoStream",
layout="centered",
initial_sidebar_state="expanded",
)
# --------------------------------------------------------------------------- #
# Theme — Claude-inspired dark with orange accent
# --------------------------------------------------------------------------- #
_CSS = """
"""
st.markdown(_CSS, unsafe_allow_html=True)
# --------------------------------------------------------------------------- #
# Session state init
# --------------------------------------------------------------------------- #
def _initial_state() -> AgentState:
return {
"messages": [],
"intent": "unknown",
"collecting_lead": False,
"lead_name": None,
"lead_email": None,
"lead_platform": None,
"lead_captured": False,
"rag_context": "",
}
if "agent_state" not in st.session_state:
st.session_state.agent_state = _initial_state()
if "display_messages" not in st.session_state:
st.session_state.display_messages = []
# --------------------------------------------------------------------------- #
# Sidebar
# --------------------------------------------------------------------------- #
with st.sidebar:
st.markdown(
'
AutoStream.
',
unsafe_allow_html=True,
)
st.markdown(
''
'AI sales assistant
',
unsafe_allow_html=True,
)
st.divider()
state = st.session_state.agent_state
intent = state.get("intent", "unknown")
st.markdown('Current intent
', unsafe_allow_html=True)
badge_class = "as-badge accent" if intent in ("high_intent", "collecting") else "as-badge"
st.markdown(f'{intent}', unsafe_allow_html=True)
if state.get("collecting_lead"):
st.markdown(
'Lead collection
',
unsafe_allow_html=True,
)
fields = [
("Name", state.get("lead_name")),
("Email", state.get("lead_email")),
("Platform", state.get("lead_platform")),
]
rows = []
for key, val in fields:
cls = "val done" if val else "val pending"
display = val or "—"
rows.append(
f'{key}'
f'{display}
'
)
st.markdown("".join(rows), unsafe_allow_html=True)
if state.get("lead_captured"):
st.markdown(
'Lead captured
',
unsafe_allow_html=True,
)
st.divider()
if st.button("New conversation", use_container_width=True):
st.session_state.agent_state = _initial_state()
st.session_state.display_messages = []
st.rerun()
# --------------------------------------------------------------------------- #
# Main chat UI
# --------------------------------------------------------------------------- #
st.markdown(
'AutoStream
'
''
'Ask about pricing, features, or start a plan.
',
unsafe_allow_html=True,
)
for msg in st.session_state.display_messages:
with st.chat_message(msg["role"]):
st.markdown(msg["content"])
if prompt := st.chat_input("Message AutoStream…", disabled=state.get("lead_captured", False)):
st.session_state.display_messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.markdown(prompt)
with st.chat_message("assistant"):
with st.spinner(""):
app = get_app()
current = st.session_state.agent_state
invoke_state = {
**current,
"messages": list(current["messages"]) + [HumanMessage(content=prompt)],
}
result = app.invoke(invoke_state)
st.session_state.agent_state = result
reply = ""
for msg in reversed(result["messages"]):
if isinstance(msg, AIMessage):
reply = msg.content
break
st.markdown(reply)
st.session_state.display_messages.append({"role": "assistant", "content": reply})
st.rerun()