Spaces:
Sleeping
Sleeping
File size: 4,932 Bytes
26215e2 2497eb4 e73e89e 26215e2 e73e89e 2497eb4 e73e89e 26215e2 2497eb4 e73e89e 2497eb4 e73e89e 26215e2 2497eb4 e73e89e 26215e2 2497eb4 e73e89e 2497eb4 26215e2 e73e89e 2497eb4 e73e89e 26215e2 2497eb4 26215e2 2497eb4 26215e2 2497eb4 e73e89e 26215e2 2497eb4 e73e89e 2497eb4 26215e2 2497eb4 e73e89e 2497eb4 e73e89e 2497eb4 26215e2 2497eb4 e73e89e 2497eb4 e73e89e 2497eb4 e73e89e 2497eb4 e73e89e 26215e2 2497eb4 e73e89e 2497eb4 e73e89e 2497eb4 e73e89e 26215e2 2497eb4 e73e89e 2497eb4 e73e89e 2497eb4 e73e89e |
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 |
import gradio as gr
import tempfile
from datetime import datetime
# ---------------------------------------------------------------------------
# Backend logic per mode (stub functions to plug your real engine into)
# ---------------------------------------------------------------------------
def handle_threat_intel(message, files):
out = f"[Threat Intel] Processed: {message}"
if files:
out += f" | Files: {[f.name for f in files]}"
return out
def handle_translation(message, files):
out = f"[Translation] Interpreted: {message}"
if files:
out += " | (Files attached for context)"
return out
def handle_marketplace_watch(message, files):
out = f"[Marketplace Watch] Monitoring request: {message}"
return out
def handle_analyst_tools(message, files):
out = f"[Analyst Tools] Action: {message}"
return out
MODE_ROUTER = {
"Threat Intel": handle_threat_intel,
"Translation": handle_translation,
"Marketplace Watch": handle_marketplace_watch,
"Analyst Tools": handle_analyst_tools,
}
# ---------------------------------------------------------------------------
# Core message processing
# ---------------------------------------------------------------------------
def process_message(message, files, history, mode):
if not message and not files:
return history, history # no-op
handler = MODE_ROUTER.get(mode, handle_threat_intel)
response = handler(message or "(no text, files only)", files)
user_label = f"{mode}: {message or '[files only]'}"
history = history + [(user_label, response)]
# Clear text input on submit handled by UI (by setting value="")
return history, history
def clear_chat():
return [], []
def download_chat(history):
# Convert chat history to a text file and return its path
if not history:
content = "No conversation yet.\n"
else:
lines = []
for user_msg, bot_msg in history:
lines.append(f"[User]: {user_msg}")
lines.append(f"[System]: {bot_msg}")
lines.append("") # blank line between turns
content = "\n".join(lines)
tmp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".txt")
with open(tmp_file.name, "w", encoding="utf-8") as f:
f.write(content)
return tmp_file.name
# ---------------------------------------------------------------------------
# Mobile-first UI
# ---------------------------------------------------------------------------
with gr.Blocks(title="Mobile-First Intelligence Console") as demo:
gr.Markdown("## 🛰 Intelligence Console")
# Global chat state
chat_state = gr.State([])
# Mode selector at top (full width)
mode = gr.Radio(
["Threat Intel", "Translation", "Marketplace Watch", "Analyst Tools"],
value="Threat Intel",
label="Mode",
interactive=True
)
# Chat area (full-width, tall enough but scrollable on mobile)
chat = gr.Chatbot(
label="Dialogue",
height=430,
show_copy_button=True
)
# Utility + attachments collapsed on mobile to reduce clutter
with gr.Accordion("Attachments & Utilities", open=False):
file_input = gr.File(
label="Upload files (logs, screenshots, docs)",
file_count="multiple"
)
with gr.Row(variant="compact"):
clear_btn = gr.Button("Clear Chat", variant="secondary")
download_btn = gr.Button("Download Transcript", variant="secondary")
download_file = gr.File(
label="Transcript File",
interactive=False
)
# Input bar at bottom: textbox + send button in a compact row
with gr.Row(variant="compact"):
user_input = gr.Textbox(
placeholder="Type your message...",
label="",
scale=5
)
send_btn = gr.Button("Send", variant="primary", scale=1)
# -----------------------------------------------------------------------
# Event wiring
# -----------------------------------------------------------------------
# Send via button
send_btn.click(
fn=process_message,
inputs=[user_input, file_input, chat_state, mode],
outputs=[chat, chat_state]
).then(
lambda: "",
inputs=None,
outputs=user_input # clear input after send
)
# Send via Enter key
user_input.submit(
fn=process_message,
inputs=[user_input, file_input, chat_state, mode],
outputs=[chat, chat_state]
).then(
lambda: "",
inputs=None,
outputs=user_input
)
# Clear chat
clear_btn.click(
fn=clear_chat,
inputs=None,
outputs=[chat, chat_state]
)
# Download transcript
download_btn.click(
fn=download_chat,
inputs=chat_state,
outputs=download_file
)
demo.launch() |