File size: 5,642 Bytes
9829f79
 
346c818
54c993d
9829f79
346c818
 
 
 
 
 
 
 
 
9829f79
346c818
 
 
 
 
 
 
 
f24ee2a
346c818
 
 
 
 
 
 
 
 
 
 
9829f79
346c818
 
 
 
9829f79
346c818
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9829f79
 
 
 
 
346c818
 
9829f79
346c818
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f24ee2a
346c818
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f24ee2a
 
346c818
 
f24ee2a
346c818
f24ee2a
346c818
 
 
 
 
 
 
 
 
 
 
f24ee2a
346c818
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
import streamlit as st
import base64
import os
import time  # <-- This was missing!
from io import BytesIO
from src.main import graph
from src.schema import AgentState
# --- PAGE CONFIG ---
st.set_page_config(
    page_title="NewsAgent Pro v2", 
    page_icon="πŸ—žοΈ", 
    layout="wide",
    initial_sidebar_state="expanded"
)

# --- CUSTOM CSS ---
st.markdown("""
<style>
    .stButton>button {width: 100%; border-radius: 8px; font-weight: bold;}
    .reportview-container {margin-top: -2em;}
    h1 {color: #FF4B4B;}
</style>
""", unsafe_allow_html=True)

# --- SIDEBAR ---
with st.sidebar:
    st.title("πŸ€– Agent Command")
    st.info("System Online v2.0")
    st.markdown("### βš™οΈ Engine Specs")
    st.markdown("- **Planner:** Llama 3.3 (Groq)")
    st.markdown("- **Writer:** Gemini 2.5 / Groq")
    st.markdown("- **Visuals:** Flux.1 Schnell")
    
    st.markdown("---")
    st.write("Authored by **Lexpertz R&D**")

# --- MAIN INTERFACE ---
st.title("πŸ—žοΈ NewsAgent Pro")
st.markdown("### Autonomous Multi-Modal Content Engine")
st.caption("Enter a topic. The AI swarm will Research, Plan, Write, and Design assets automatically.")

# Input Section
with st.container():
    col_input, col_btn = st.columns([3, 1])
    with col_input:
        topic = st.text_input("Mission Objective (Topic)", placeholder="e.g. DeepSeek vs OpenAI rivalry")
    with col_btn:
        platform = st.selectbox("Target Platform", ["Twitter", "LinkedIn"])
        run_btn = st.button("πŸš€ Launch Agents", type="primary")

# --- SESSION STATE INITIALIZATION ---
if "generated_content" not in st.session_state:
    st.session_state.generated_content = None
if "generated_image" not in st.session_state:
    st.session_state.generated_image = None
if "sources" not in st.session_state:
    st.session_state.sources = []

# --- EXECUTION LOGIC ---
if run_btn and topic:
    # Reset State
    st.session_state.generated_content = None
    st.session_state.generated_image = None
    
    status_box = st.status("πŸš€ Initializing Agent Swarm...", expanded=True)
    
    try:
        # Initialize Pydantic State
        initial_state = AgentState(
            topic=topic,
            platform=platform.lower()
        )
        
        # Run Graph
        curr_state = initial_state
        
        # We iterate through the stream updates
        for event in graph.stream(initial_state):
            for node_name, values in event.items():
                # Skip empty updates
                if not values:
                    continue
                
                # Update status based on active agent
                if node_name == "planner":
                    status_box.write("🧠 **Planner:** Strategy & Hook defined.")
                elif node_name == "researcher":
                    status_box.write(f"πŸ•΅οΈβ€β™‚οΈ **Researcher:** Gathered data.")
                elif node_name == "writer":
                    status_box.write("✍️ **Writer:** Draft generated.")
                elif node_name == "designer":
                    status_box.write("🎨 **Designer:** Visual asset rendered.")

                # Update local state dict to track progress
                # Note: LangGraph returns the *changes*, so we update our tracker
                # For simplicity in this UI loop, we grab final artifacts at the end
                if "final_thread" in values:
                    st.session_state.generated_content = values["final_thread"]
                if "image_url" in values:
                    st.session_state.generated_image = values["image_url"]
                if "research_data" in values:
                    # Extract sources for display
                    # Assuming research_data is a string in the final state or list of dicts
                    # Adjust based on your researcher.py output
                    pass 

        status_box.update(label="βœ… Mission Accomplished", state="complete", expanded=False)

    except Exception as e:
        status_box.update(label="❌ Mission Failed", state="error")
        st.error(f"Agent Logic Error: {str(e)}")

# --- RESULTS DISPLAY ---
if st.session_state.generated_content or st.session_state.generated_image:
    st.divider()
    res_col1, res_col2 = st.columns([1, 1])

    # LEFT: Visuals
    with res_col1:
        st.subheader("🎨 Visual Asset")
        if st.session_state.generated_image:
            img_path = st.session_state.generated_image
            if os.path.exists(img_path):
                st.image(img_path, caption="Viral Cover Image", use_container_width=True)
                
                # Download Button
                with open(img_path, "rb") as file:
                    btn = st.download_button(
                        label="⬇️ Download PNG",
                        data=file,
                        file_name=f"newsagent_{int(time.time())}.png",
                        mime="image/png"
                    )
            else:
                st.warning("Image file missing (Docker ephemeral storage).")
        else:
            st.info("No visual generated for this run.")

    # RIGHT: Copy
    with res_col2:
        st.subheader(f"πŸ“ {platform} Draft")
        content = st.session_state.generated_content
        
        if content:
            if isinstance(content, list): # Twitter Thread
                for i, tweet in enumerate(content):
                    st.text_area(f"Tweet {i+1}", value=tweet, height=120)
            else: # LinkedIn Post
                st.text_area("Post Content", value=content, height=400)
        else:
            st.info("No text content generated.")