Ai-Agent-Streamlit / src /streamlit_app.py
MaroofTechSorcerer's picture
Update src/streamlit_app.py
82c04df verified
import streamlit as st
import json
import os
import subprocess
import time
import pandas as pd
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
st.set_page_config(layout="wide")
# Paths
SALES_SCRIPT_FILE = 'sales_script.txt'
NUMBERS_FILE = 'numbers.txt'
LOG_DIR = 'call_logs'
APP_DATA_DIR = 'application_data'
WEBHOOK_SERVER_FILE = 'webhook_server.py'
# --- Helper Functions ---
def load_sales_script():
if os.path.exists(SALES_SCRIPT_FILE):
with open(SALES_SCRIPT_FILE, 'r') as f:
return f.read()
return ""
def save_sales_script(script):
with open(SALES_SCRIPT_FILE, 'w') as f:
f.write(script)
def load_numbers():
if os.path.exists(NUMBERS_FILE):
with open(NUMBERS_FILE, 'r') as f:
return [line.strip() for line in f.readlines()]
return []
def save_numbers(numbers):
with open(NUMBERS_FILE, 'w') as f:
f.write('\n'.join(numbers))
@st.cache_data
def get_application_data():
data = []
if os.path.exists(APP_DATA_DIR):
for filename in os.listdir(APP_DATA_DIR):
if filename.endswith(".json"):
with open(os.path.join(APP_DATA_DIR, filename), 'r') as f:
call_data = json.load(f)
call_data['call_sid'] = filename.replace('.json', '')
data.append(call_data)
return pd.DataFrame(data)
# --- UI ---
st.title("AI Sales Calling Agent")
# --- Sales Script ---
with st.expander("Sales Script"):
sales_script = st.text_area("Edit Sales Script", value=load_sales_script(), height=200)
if st.button("Save Script"):
save_sales_script(sales_script)
st.success("Sales script saved!")
# --- Numbers ---
with st.expander("Manage Numbers"):
numbers = st.text_area("Enter numbers to call (one per line)", value='\n'.join(load_numbers()), height=150)
if st.button("Save Numbers"):
save_numbers(numbers.split('\n'))
st.success("Numbers saved!")
def get_huggingface_url():
hf_space_id = os.environ.get("HF_SPACE_ID")
if hf_space_id:
return f"https://{hf_space_id.replace('/', '-')}.hf.space"
return None
# --- Call Control ---
with st.expander("Call Control"):
st.info("When running on Hugging Face Spaces, the webhook server will start automatically.")
if os.environ.get("HF_SPACE_ID") and not hasattr(st, 'webhook_process'):
try:
st.webhook_process = subprocess.Popen(["python", WEBHOOK_SERVER_FILE])
st.success("Webhook server started automatically on Hugging Face Space.")
except Exception as e:
st.error(f"Error starting webhook server: {e}")
webhook_url = get_huggingface_url()
if webhook_url:
st.success(f"Webhook URL detected: {webhook_url}")
else:
st.warning("Could not determine Hugging Face URL. Please run this in a Hugging Face Space.")
number_to_call = st.selectbox("Select number to call", load_numbers())
if st.button("Initiate Call"):
if webhook_url:
try:
from twilio.rest import Client
client = Client(os.environ.get('TWILIO_ACCOUNT_SID'), os.environ.get('TWILIO_AUTH_TOKEN'))
call = client.calls.create(
to=number_to_call,
from_=os.environ.get('TWILIO_PHONE_NUMBER'),
url=f"{webhook_url}",
status_callback=f"{webhook_url}/status",
status_callback_method="POST",
status_callback_event=['completed']
)
st.success(f"Call initiated to {number_to_call} (SID: {call.sid})")
except Exception as e:
st.error(f"Error initiating call: {e}")
else:
st.error("Webhook URL is not set. Cannot initiate call.")
# --- Real-time Logs & Data ---
st.header("Live Call Status")
log_placeholder = st.empty()
class LogHandler(FileSystemEventHandler):
def on_modified(self, event):
if not event.is_directory and event.src_path.endswith(".log"):
with open(event.src_path, "r") as f:
log_placeholder.text_area("Logs", f.read(), height=300)
if not os.path.exists(LOG_DIR):
os.makedirs(LOG_DIR)
observer = Observer()
observer.schedule(LogHandler(), LOG_DIR, recursive=True)
observer.start()
# --- Application Data ---
st.header("Extracted Application Data")
df = get_application_data()
if not df.empty:
st.dataframe(df)
csv = df.to_csv(index=False).encode('utf-8')
st.download_button(
label="Download Application Data as CSV",
data=csv,
file_name='application_data.csv',
mime='text/csv',
)
else:
st.info("No application data found.")