Replace magic numbers with MessageType constants
This commit replaces all hardcoded message type integers (0, 1, 2, 3, 4, 5) with named constants from a new MessageType module, improving code readability and maintainability across the codebase.
This commit is contained in:
parent
2dca1664dd
commit
752d455312
9 changed files with 302 additions and 157 deletions
|
|
@ -1,3 +1,4 @@
|
|||
use crate::shared::message_types::MessageType;
|
||||
use crate::shared::models::{BotResponse, UserSession};
|
||||
use crate::shared::state::AppState;
|
||||
use log::{error, trace};
|
||||
|
|
@ -84,7 +85,7 @@ pub async fn execute_talk(
|
|||
session_id: user_session.id.to_string(),
|
||||
channel: "web".to_string(),
|
||||
content: message,
|
||||
message_type: 1,
|
||||
message_type: MessageType::USER,
|
||||
stream_token: None,
|
||||
is_complete: true,
|
||||
suggestions,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::core::bot::channels::{
|
||||
instagram::InstagramAdapter, teams::TeamsAdapter, whatsapp::WhatsAppAdapter, ChannelAdapter,
|
||||
};
|
||||
use crate::shared::message_types::MessageType;
|
||||
use crate::shared::models::UserSession;
|
||||
use crate::shared::state::AppState;
|
||||
use log::{error, trace};
|
||||
|
|
@ -200,7 +201,7 @@ async fn send_message_to_recipient(
|
|||
user_id: recipient_id.clone(),
|
||||
channel: "whatsapp".to_string(),
|
||||
content: message.to_string(),
|
||||
message_type: 0,
|
||||
message_type: MessageType::EXTERNAL,
|
||||
stream_token: None,
|
||||
is_complete: true,
|
||||
suggestions: vec![],
|
||||
|
|
@ -218,7 +219,7 @@ async fn send_message_to_recipient(
|
|||
user_id: recipient_id.clone(),
|
||||
channel: "instagram".to_string(),
|
||||
content: message.to_string(),
|
||||
message_type: 0,
|
||||
message_type: MessageType::EXTERNAL,
|
||||
stream_token: None,
|
||||
is_complete: true,
|
||||
suggestions: vec![],
|
||||
|
|
@ -236,7 +237,7 @@ async fn send_message_to_recipient(
|
|||
user_id: recipient_id.clone(),
|
||||
channel: "teams".to_string(),
|
||||
content: message.to_string(),
|
||||
message_type: 0,
|
||||
message_type: MessageType::EXTERNAL,
|
||||
stream_token: None,
|
||||
is_complete: true,
|
||||
suggestions: vec![],
|
||||
|
|
@ -588,7 +589,7 @@ async fn send_web_message(
|
|||
session_id: session_id.to_string(),
|
||||
channel: "web".to_string(),
|
||||
content: message.to_string(),
|
||||
message_type: 1,
|
||||
message_type: MessageType::USER,
|
||||
stream_token: None,
|
||||
is_complete: true,
|
||||
suggestions: Vec::new(),
|
||||
|
|
|
|||
|
|
@ -1,113 +1,114 @@
|
|||
use crate::shared::message_types::MessageType;
|
||||
use crate::shared::models::BotResponse;
|
||||
use crate::shared::state::AppState;
|
||||
use color_eyre::Result;
|
||||
use std::sync::Arc;
|
||||
use crate::shared::state::AppState;
|
||||
use crate::shared::models::BotResponse;
|
||||
use tokio::sync::mpsc;
|
||||
use uuid::Uuid;
|
||||
pub struct ChatPanel {
|
||||
pub messages: Vec<String>,
|
||||
pub input_buffer: String,
|
||||
pub session_id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
pub response_rx: Option<mpsc::Receiver<BotResponse>>,
|
||||
pub messages: Vec<String>,
|
||||
pub input_buffer: String,
|
||||
pub session_id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
pub response_rx: Option<mpsc::Receiver<BotResponse>>,
|
||||
}
|
||||
impl ChatPanel {
|
||||
pub fn new(_app_state: Arc<AppState>) -> Self {
|
||||
Self {
|
||||
messages: vec!["Welcome to General Bots Console Chat!".to_string()],
|
||||
input_buffer: String::new(),
|
||||
session_id: Uuid::new_v4(),
|
||||
user_id: Uuid::new_v4(),
|
||||
response_rx: None,
|
||||
}
|
||||
}
|
||||
pub fn add_char(&mut self, c: char) {
|
||||
self.input_buffer.push(c);
|
||||
}
|
||||
pub fn backspace(&mut self) {
|
||||
self.input_buffer.pop();
|
||||
}
|
||||
pub async fn send_message(&mut self, bot_name: &str, app_state: &Arc<AppState>) -> Result<()> {
|
||||
if self.input_buffer.trim().is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let message = self.input_buffer.clone();
|
||||
self.messages.push(format!("You: {}", message));
|
||||
self.input_buffer.clear();
|
||||
let bot_id = self.get_bot_id(bot_name, app_state).await?;
|
||||
let user_message = crate::shared::models::UserMessage {
|
||||
bot_id: bot_id.to_string(),
|
||||
user_id: self.user_id.to_string(),
|
||||
session_id: self.session_id.to_string(),
|
||||
channel: "console".to_string(),
|
||||
content: message,
|
||||
message_type: 1,
|
||||
media_url: None,
|
||||
timestamp: chrono::Utc::now(),
|
||||
context_name: None,
|
||||
};
|
||||
let (tx, rx) = mpsc::channel::<BotResponse>(100);
|
||||
self.response_rx = Some(rx);
|
||||
let orchestrator = crate::bot::BotOrchestrator::new(app_state.clone());
|
||||
let _ = orchestrator.stream_response(user_message, tx).await;
|
||||
Ok(())
|
||||
}
|
||||
pub async fn poll_response(&mut self, _bot_name: &str) -> Result<()> {
|
||||
if let Some(rx) = &mut self.response_rx {
|
||||
while let Ok(response) = rx.try_recv() {
|
||||
if !response.content.is_empty() && !response.is_complete {
|
||||
if let Some(last_msg) = self.messages.last_mut() {
|
||||
if last_msg.starts_with("Bot: ") {
|
||||
last_msg.push_str(&response.content);
|
||||
} else {
|
||||
self.messages.push(format!("Bot: {}", response.content));
|
||||
}
|
||||
} else {
|
||||
self.messages.push(format!("Bot: {}", response.content));
|
||||
}
|
||||
}
|
||||
if response.is_complete && response.content.is_empty() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
async fn get_bot_id(&self, bot_name: &str, app_state: &Arc<AppState>) -> Result<Uuid> {
|
||||
use crate::shared::models::schema::bots::dsl::*;
|
||||
use diesel::prelude::*;
|
||||
let mut conn = app_state.conn.get().unwrap();
|
||||
let bot_id = bots
|
||||
.filter(name.eq(bot_name))
|
||||
.select(id)
|
||||
.first::<Uuid>(&mut *conn)?;
|
||||
Ok(bot_id)
|
||||
}
|
||||
pub fn render(&self) -> String {
|
||||
let mut lines = Vec::new();
|
||||
lines.push("╔═══════════════════════════════════════╗".to_string());
|
||||
lines.push("║ CONVERSATION ║".to_string());
|
||||
lines.push("╚═══════════════════════════════════════╝".to_string());
|
||||
lines.push("".to_string());
|
||||
let visible_start = if self.messages.len() > 15 {
|
||||
self.messages.len() - 15
|
||||
} else {
|
||||
0
|
||||
};
|
||||
for msg in &self.messages[visible_start..] {
|
||||
if msg.starts_with("You: ") {
|
||||
lines.push(format!(" {}", msg));
|
||||
} else if msg.starts_with("Bot: ") {
|
||||
lines.push(format!(" {}", msg));
|
||||
} else {
|
||||
lines.push(format!(" {}", msg));
|
||||
}
|
||||
}
|
||||
lines.push("".to_string());
|
||||
lines.push("─────────────────────────────────────────".to_string());
|
||||
lines.push(format!(" > {}_", self.input_buffer));
|
||||
lines.push("".to_string());
|
||||
lines.push(" Enter: Send | Tab: Switch Panel".to_string());
|
||||
lines.join("\n")
|
||||
}
|
||||
pub fn new(_app_state: Arc<AppState>) -> Self {
|
||||
Self {
|
||||
messages: vec!["Welcome to General Bots Console Chat!".to_string()],
|
||||
input_buffer: String::new(),
|
||||
session_id: Uuid::new_v4(),
|
||||
user_id: Uuid::new_v4(),
|
||||
response_rx: None,
|
||||
}
|
||||
}
|
||||
pub fn add_char(&mut self, c: char) {
|
||||
self.input_buffer.push(c);
|
||||
}
|
||||
pub fn backspace(&mut self) {
|
||||
self.input_buffer.pop();
|
||||
}
|
||||
pub async fn send_message(&mut self, bot_name: &str, app_state: &Arc<AppState>) -> Result<()> {
|
||||
if self.input_buffer.trim().is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let message = self.input_buffer.clone();
|
||||
self.messages.push(format!("You: {}", message));
|
||||
self.input_buffer.clear();
|
||||
let bot_id = self.get_bot_id(bot_name, app_state).await?;
|
||||
let user_message = crate::shared::models::UserMessage {
|
||||
bot_id: bot_id.to_string(),
|
||||
user_id: self.user_id.to_string(),
|
||||
session_id: self.session_id.to_string(),
|
||||
channel: "console".to_string(),
|
||||
content: message,
|
||||
message_type: MessageType::USER,
|
||||
media_url: None,
|
||||
timestamp: chrono::Utc::now(),
|
||||
context_name: None,
|
||||
};
|
||||
let (tx, rx) = mpsc::channel::<BotResponse>(100);
|
||||
self.response_rx = Some(rx);
|
||||
let orchestrator = crate::bot::BotOrchestrator::new(app_state.clone());
|
||||
let _ = orchestrator.stream_response(user_message, tx).await;
|
||||
Ok(())
|
||||
}
|
||||
pub async fn poll_response(&mut self, _bot_name: &str) -> Result<()> {
|
||||
if let Some(rx) = &mut self.response_rx {
|
||||
while let Ok(response) = rx.try_recv() {
|
||||
if !response.content.is_empty() && !response.is_complete {
|
||||
if let Some(last_msg) = self.messages.last_mut() {
|
||||
if last_msg.starts_with("Bot: ") {
|
||||
last_msg.push_str(&response.content);
|
||||
} else {
|
||||
self.messages.push(format!("Bot: {}", response.content));
|
||||
}
|
||||
} else {
|
||||
self.messages.push(format!("Bot: {}", response.content));
|
||||
}
|
||||
}
|
||||
if response.is_complete && response.content.is_empty() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
async fn get_bot_id(&self, bot_name: &str, app_state: &Arc<AppState>) -> Result<Uuid> {
|
||||
use crate::shared::models::schema::bots::dsl::*;
|
||||
use diesel::prelude::*;
|
||||
let mut conn = app_state.conn.get().unwrap();
|
||||
let bot_id = bots
|
||||
.filter(name.eq(bot_name))
|
||||
.select(id)
|
||||
.first::<Uuid>(&mut *conn)?;
|
||||
Ok(bot_id)
|
||||
}
|
||||
pub fn render(&self) -> String {
|
||||
let mut lines = Vec::new();
|
||||
lines.push("╔═══════════════════════════════════════╗".to_string());
|
||||
lines.push("║ CONVERSATION ║".to_string());
|
||||
lines.push("╚═══════════════════════════════════════╝".to_string());
|
||||
lines.push("".to_string());
|
||||
let visible_start = if self.messages.len() > 15 {
|
||||
self.messages.len() - 15
|
||||
} else {
|
||||
0
|
||||
};
|
||||
for msg in &self.messages[visible_start..] {
|
||||
if msg.starts_with("You: ") {
|
||||
lines.push(format!(" {}", msg));
|
||||
} else if msg.starts_with("Bot: ") {
|
||||
lines.push(format!(" {}", msg));
|
||||
} else {
|
||||
lines.push(format!(" {}", msg));
|
||||
}
|
||||
}
|
||||
lines.push("".to_string());
|
||||
lines.push("─────────────────────────────────────────".to_string());
|
||||
lines.push(format!(" > {}_", self.input_buffer));
|
||||
lines.push("".to_string());
|
||||
lines.push(" Enter: Send | Tab: Switch Panel".to_string());
|
||||
lines.join("\n")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use crate::llm::llm_models;
|
|||
use crate::llm::OpenAIClient;
|
||||
#[cfg(feature = "nvidia")]
|
||||
use crate::nvidia::get_system_metrics;
|
||||
use crate::shared::message_types::MessageType;
|
||||
use crate::shared::models::{BotResponse, UserMessage, UserSession};
|
||||
use crate::shared::state::AppState;
|
||||
use axum::extract::ws::{Message, WebSocket};
|
||||
|
|
@ -209,7 +210,7 @@ impl BotOrchestrator {
|
|||
session_id: message.session_id.clone(),
|
||||
channel: message.channel.clone(),
|
||||
content: processed,
|
||||
message_type: 2,
|
||||
message_type: MessageType::BOT_RESPONSE,
|
||||
stream_token: None,
|
||||
is_complete: false,
|
||||
suggestions: Vec::new(),
|
||||
|
|
@ -246,7 +247,7 @@ impl BotOrchestrator {
|
|||
session_id: message.session_id.clone(),
|
||||
channel: message.channel.clone(),
|
||||
content: processed,
|
||||
message_type: 2,
|
||||
message_type: MessageType::BOT_RESPONSE,
|
||||
stream_token: None,
|
||||
is_complete: false,
|
||||
suggestions: Vec::new(),
|
||||
|
|
@ -281,7 +282,7 @@ impl BotOrchestrator {
|
|||
session_id: message.session_id.clone(),
|
||||
channel: message.channel.clone(),
|
||||
content: chunk,
|
||||
message_type: 2,
|
||||
message_type: MessageType::BOT_RESPONSE,
|
||||
stream_token: None,
|
||||
is_complete: false,
|
||||
suggestions: Vec::new(),
|
||||
|
|
@ -314,7 +315,7 @@ impl BotOrchestrator {
|
|||
session_id: message.session_id,
|
||||
channel: message.channel,
|
||||
content: full_response,
|
||||
message_type: 2,
|
||||
message_type: MessageType::BOT_RESPONSE,
|
||||
stream_token: None,
|
||||
is_complete: true,
|
||||
suggestions: Vec::new(),
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
//! - Storage abstraction for S3-compatible backends
|
||||
//! - URL processing and validation
|
||||
|
||||
use crate::shared::message_types::MessageType;
|
||||
use crate::shared::models::{BotResponse, UserMessage};
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
|
|
@ -154,7 +155,7 @@ impl MultimediaHandler for DefaultMultimediaHandler {
|
|||
session_id: session_id.to_string(),
|
||||
channel: "multimedia".to_string(),
|
||||
content,
|
||||
message_type: 0,
|
||||
message_type: MessageType::EXTERNAL,
|
||||
stream_token: None,
|
||||
is_complete: true,
|
||||
suggestions: Vec::new(),
|
||||
|
|
@ -182,7 +183,7 @@ impl MultimediaHandler for DefaultMultimediaHandler {
|
|||
session_id: session_id.to_string(),
|
||||
channel: "multimedia".to_string(),
|
||||
content: response_content,
|
||||
message_type: 0,
|
||||
message_type: MessageType::EXTERNAL,
|
||||
stream_token: None,
|
||||
is_complete: true,
|
||||
suggestions: Vec::new(),
|
||||
|
|
@ -215,7 +216,7 @@ impl MultimediaHandler for DefaultMultimediaHandler {
|
|||
session_id: session_id.to_string(),
|
||||
channel: "multimedia".to_string(),
|
||||
content: response_content,
|
||||
message_type: 0,
|
||||
message_type: MessageType::EXTERNAL,
|
||||
stream_token: None,
|
||||
is_complete: true,
|
||||
suggestions: Vec::new(),
|
||||
|
|
@ -248,7 +249,7 @@ impl MultimediaHandler for DefaultMultimediaHandler {
|
|||
session_id: session_id.to_string(),
|
||||
channel: "multimedia".to_string(),
|
||||
content: response_content,
|
||||
message_type: 0,
|
||||
message_type: MessageType::EXTERNAL,
|
||||
stream_token: None,
|
||||
is_complete: true,
|
||||
suggestions: Vec::new(),
|
||||
|
|
@ -277,7 +278,7 @@ impl MultimediaHandler for DefaultMultimediaHandler {
|
|||
session_id: session_id.to_string(),
|
||||
channel: "multimedia".to_string(),
|
||||
content: response_content,
|
||||
message_type: 0,
|
||||
message_type: MessageType::EXTERNAL,
|
||||
stream_token: None,
|
||||
is_complete: true,
|
||||
suggestions: Vec::new(),
|
||||
|
|
@ -294,7 +295,7 @@ impl MultimediaHandler for DefaultMultimediaHandler {
|
|||
session_id: session_id.to_string(),
|
||||
channel: "multimedia".to_string(),
|
||||
content: "Message received and processing...".to_string(),
|
||||
message_type: 0,
|
||||
message_type: MessageType::EXTERNAL,
|
||||
stream_token: None,
|
||||
is_complete: true,
|
||||
suggestions: Vec::new(),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
pub mod admin;
|
||||
pub mod analytics;
|
||||
pub mod message_types;
|
||||
pub mod models;
|
||||
pub mod state;
|
||||
pub mod utils;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use crate::shared::message_types::MessageType;
|
||||
use chrono::{DateTime, Utc};
|
||||
use diesel::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
|
@ -51,7 +52,7 @@ pub struct UserMessage {
|
|||
pub session_id: String,
|
||||
pub channel: String,
|
||||
pub content: String,
|
||||
pub message_type: i32,
|
||||
pub message_type: MessageType,
|
||||
pub media_url: Option<String>,
|
||||
pub timestamp: DateTime<Utc>,
|
||||
pub context_name: Option<String>,
|
||||
|
|
@ -68,7 +69,7 @@ pub struct BotResponse {
|
|||
pub session_id: String,
|
||||
pub channel: String,
|
||||
pub content: String,
|
||||
pub message_type: i32,
|
||||
pub message_type: MessageType,
|
||||
pub stream_token: Option<String>,
|
||||
pub is_complete: bool,
|
||||
pub suggestions: Vec<Suggestion>,
|
||||
|
|
@ -90,7 +91,7 @@ impl BotResponse {
|
|||
session_id: session_id.to_string(),
|
||||
channel,
|
||||
content,
|
||||
message_type: 2,
|
||||
message_type: MessageType::BOT_RESPONSE,
|
||||
stream_token: None,
|
||||
is_complete: true,
|
||||
suggestions: Vec::new(),
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
use crate::basic::compiler::BasicCompiler;
|
||||
use crate::config::ConfigManager;
|
||||
use crate::core::kb::KnowledgeBaseManager;
|
||||
use crate::shared::message_types::MessageType;
|
||||
use crate::shared::state::AppState;
|
||||
use aws_sdk_s3::Client;
|
||||
use log::{debug, error, info};
|
||||
|
|
@ -345,7 +346,7 @@ impl DriveMonitor {
|
|||
session_id: session_id.clone(),
|
||||
channel: "web".to_string(),
|
||||
content: serde_json::to_string(&theme_data)?,
|
||||
message_type: 2,
|
||||
message_type: MessageType::BOT_RESPONSE,
|
||||
stream_token: None,
|
||||
is_complete: true,
|
||||
suggestions: Vec::new(),
|
||||
|
|
|
|||
|
|
@ -4,6 +4,17 @@
|
|||
<meta charset="utf-8" />
|
||||
<title>General Bots</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||||
<script>
|
||||
// Message Type Constants inline since we don't have a /shared route
|
||||
const MessageType = {
|
||||
EXTERNAL: 0,
|
||||
USER: 1,
|
||||
BOT_RESPONSE: 2,
|
||||
CONTINUE: 3,
|
||||
SUGGESTION: 4,
|
||||
CONTEXT_CHANGE: 5,
|
||||
};
|
||||
</script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/livekit-client/dist/livekit-client.umd.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||
|
|
@ -733,12 +744,21 @@
|
|||
isUserScrolling = false,
|
||||
autoScrollEnabled = true,
|
||||
isContextChange = false;
|
||||
const maxReconnectAttempts = 5,
|
||||
messagesDiv = document.getElementById("messages"),
|
||||
input = document.getElementById("messageInput"),
|
||||
sendBtn = document.getElementById("sendBtn"),
|
||||
voiceBtn = document.getElementById("voiceBtn"),
|
||||
connectionStatus = document.getElementById("connectionStatus"),
|
||||
const maxReconnectAttempts = 5;
|
||||
let messagesDiv = document.getElementById("messages");
|
||||
let input = document.getElementById("messageInput");
|
||||
let sendBtn = document.getElementById("sendBtn");
|
||||
let voiceBtn = document.getElementById("voiceBtn");
|
||||
|
||||
// Debug element initialization
|
||||
console.log("Element initialization:");
|
||||
console.log("messagesDiv:", messagesDiv);
|
||||
console.log("input:", input);
|
||||
console.log("sendBtn:", sendBtn);
|
||||
console.log("voiceBtn:", voiceBtn);
|
||||
|
||||
const connectionStatus =
|
||||
document.getElementById("connectionStatus"),
|
||||
flashOverlay = document.getElementById("flashOverlay"),
|
||||
suggestionsContainer = document.getElementById("suggestions"),
|
||||
floatLogo = document.getElementById("floatLogo"),
|
||||
|
|
@ -878,17 +898,29 @@
|
|||
|
||||
async function initializeAuth() {
|
||||
try {
|
||||
console.log("Starting auth initialization...");
|
||||
updateConnectionStatus("connecting");
|
||||
const p = window.location.pathname
|
||||
.split("/")
|
||||
.filter((s) => s),
|
||||
b = p.length > 0 ? p[0] : "default",
|
||||
r = await fetch(
|
||||
`http://localhost:8080/api/auth?bot_name=${encodeURIComponent(b)}`,
|
||||
b = p.length > 0 ? p[0] : "default";
|
||||
console.log("Bot name:", b);
|
||||
const r = await fetch(
|
||||
`/api/auth?bot_name=${encodeURIComponent(b)}`,
|
||||
),
|
||||
a = await r.json();
|
||||
console.log("Auth response:", a);
|
||||
currentUserId = a.user_id;
|
||||
currentSessionId = a.session_id;
|
||||
currentBotId = a.bot_id || "default_bot";
|
||||
console.log(
|
||||
"Auth initialized - User:",
|
||||
currentUserId,
|
||||
"Session:",
|
||||
currentSessionId,
|
||||
"Bot:",
|
||||
currentBotId,
|
||||
);
|
||||
connectWebSocket();
|
||||
loadSessions();
|
||||
} catch (e) {
|
||||
|
|
@ -984,6 +1016,7 @@
|
|||
const u = getWebSocketUrl();
|
||||
ws = new WebSocket(u);
|
||||
ws.onmessage = function (e) {
|
||||
console.log("WebSocket message received:", e.data);
|
||||
try {
|
||||
if (!e.data || e.data.trim() === "") {
|
||||
console.warn("Empty WebSocket message received");
|
||||
|
|
@ -997,19 +1030,35 @@
|
|||
if (r.bot_id) {
|
||||
currentBotId = r.bot_id;
|
||||
}
|
||||
if (r.message_type === 2) {
|
||||
try {
|
||||
const d = JSON.parse(r.content);
|
||||
handleEvent(d.event, d.data);
|
||||
} catch (parseErr) {
|
||||
console.error(
|
||||
"Failed to parse event content:",
|
||||
parseErr,
|
||||
);
|
||||
// BOT_RESPONSE type is used for both regular streaming content and special event messages
|
||||
// Event messages have JSON-encoded content with 'event' and 'data' properties
|
||||
// Regular messages have plain text content that should be displayed directly
|
||||
if (r.message_type === MessageType.BOT_RESPONSE) {
|
||||
// Check if content looks like JSON (starts with { or [)
|
||||
const contentTrimmed = r.content.trim();
|
||||
if (
|
||||
contentTrimmed.startsWith("{") ||
|
||||
contentTrimmed.startsWith("[")
|
||||
) {
|
||||
try {
|
||||
const d = JSON.parse(r.content);
|
||||
if (d.event && d.data) {
|
||||
// This is an event message
|
||||
handleEvent(d.event, d.data);
|
||||
return;
|
||||
}
|
||||
} catch (parseErr) {
|
||||
// Not a valid event message, treat as regular content
|
||||
console.debug(
|
||||
"Content is not an event message, processing as regular message",
|
||||
);
|
||||
}
|
||||
}
|
||||
// Process as regular message content
|
||||
processMessageContent(r);
|
||||
return;
|
||||
}
|
||||
if (r.message_type === 5) {
|
||||
if (r.message_type === MessageType.CONTEXT_CHANGE) {
|
||||
isContextChange = true;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1024,7 +1073,10 @@
|
|||
}
|
||||
};
|
||||
ws.onopen = function () {
|
||||
console.log("Connected to WebSocket");
|
||||
console.log(
|
||||
"Connected to WebSocket, readyState:",
|
||||
ws.readyState,
|
||||
);
|
||||
updateConnectionStatus("connected");
|
||||
reconnectAttempts = 0;
|
||||
hasReceivedInitialMessage = false;
|
||||
|
|
@ -1218,7 +1270,7 @@
|
|||
session_id: currentSessionId,
|
||||
channel: "web",
|
||||
content: "continue",
|
||||
message_type: 3,
|
||||
message_type: MessageType.CONTINUE,
|
||||
media_url: null,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
|
|
@ -1327,7 +1379,8 @@
|
|||
const h = (e) => {
|
||||
const d = JSON.parse(e.data);
|
||||
if (
|
||||
d.message_type === 5 &&
|
||||
d.message_type ===
|
||||
MessageType.CONTEXT_CHANGE &&
|
||||
d.context_name === c
|
||||
) {
|
||||
ws.removeEventListener("message", h);
|
||||
|
|
@ -1341,7 +1394,7 @@
|
|||
session_id: currentSessionId,
|
||||
channel: "web",
|
||||
content: t,
|
||||
message_type: 4,
|
||||
message_type: MessageType.SUGGESTION,
|
||||
is_suggestion: true,
|
||||
context_name: c,
|
||||
timestamp: new Date().toISOString(),
|
||||
|
|
@ -1367,12 +1420,42 @@
|
|||
}
|
||||
|
||||
async function sendMessage() {
|
||||
console.log("=== sendMessage called ===");
|
||||
console.log("input element:", input);
|
||||
console.log(
|
||||
"input.value:",
|
||||
input ? input.value : "input is null",
|
||||
);
|
||||
|
||||
if (pendingContextChange) {
|
||||
await pendingContextChange;
|
||||
pendingContextChange = null;
|
||||
}
|
||||
|
||||
if (!input) {
|
||||
console.error("Input element is null!");
|
||||
return;
|
||||
}
|
||||
|
||||
const m = input.value.trim();
|
||||
if (!m || !ws || ws.readyState !== WebSocket.OPEN) {
|
||||
console.log(
|
||||
"Attempting to send message:",
|
||||
m,
|
||||
"WS state:",
|
||||
ws ? ws.readyState : "no ws",
|
||||
"WebSocket.OPEN value:",
|
||||
WebSocket.OPEN,
|
||||
);
|
||||
|
||||
if (!m) {
|
||||
console.log("Message is empty, not sending");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
||||
console.log(
|
||||
"WebSocket not connected, attempting reconnect",
|
||||
);
|
||||
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
||||
showWarning(
|
||||
"Conexão não disponível. Tentando reconectar...",
|
||||
|
|
@ -1384,27 +1467,44 @@
|
|||
if (isThinking) {
|
||||
hideThinkingIndicator();
|
||||
}
|
||||
|
||||
console.log("Adding message to UI");
|
||||
addMessage("user", m);
|
||||
|
||||
console.log("Building message data object");
|
||||
console.log("currentBotId:", currentBotId);
|
||||
console.log("currentUserId:", currentUserId);
|
||||
console.log("currentSessionId:", currentSessionId);
|
||||
|
||||
const d = {
|
||||
bot_id: currentBotId,
|
||||
bot_id: currentBotId || "default_bot",
|
||||
user_id: currentUserId,
|
||||
session_id: currentSessionId,
|
||||
channel: "web",
|
||||
content: m,
|
||||
message_type: 1,
|
||||
message_type: MessageType.USER,
|
||||
media_url: null,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
ws.send(JSON.stringify(d));
|
||||
console.log("Message data object:", JSON.stringify(d, null, 2));
|
||||
|
||||
try {
|
||||
const messageString = JSON.stringify(d);
|
||||
console.log("Stringified message:", messageString);
|
||||
console.log("About to call ws.send()");
|
||||
ws.send(messageString);
|
||||
console.log("ws.send() completed successfully");
|
||||
} catch (error) {
|
||||
console.error("Error sending message:", error);
|
||||
console.error("Error stack:", error.stack);
|
||||
}
|
||||
|
||||
console.log("Clearing input field");
|
||||
input.value = "";
|
||||
input.focus();
|
||||
console.log("=== sendMessage completed ===");
|
||||
}
|
||||
|
||||
sendBtn.onclick = sendMessage;
|
||||
input.addEventListener("keypress", (e) => {
|
||||
if (e.key === "Enter") sendMessage();
|
||||
});
|
||||
|
||||
async function toggleVoiceMode() {
|
||||
isVoiceMode = !isVoiceMode;
|
||||
const v = document.getElementById("voiceToggle");
|
||||
|
|
@ -1569,7 +1669,44 @@
|
|||
scrollToBottomBtn.classList.remove("visible");
|
||||
}
|
||||
|
||||
window.addEventListener("load", initializeAuth);
|
||||
window.addEventListener("load", () => {
|
||||
console.log("Page loaded, initializing...");
|
||||
|
||||
// Re-get elements after DOM is ready
|
||||
messagesDiv = document.getElementById("messages");
|
||||
input = document.getElementById("messageInput");
|
||||
sendBtn = document.getElementById("sendBtn");
|
||||
voiceBtn = document.getElementById("voiceBtn");
|
||||
|
||||
console.log("After load - input:", !!input);
|
||||
console.log("After load - sendBtn:", !!sendBtn);
|
||||
|
||||
// Attach event listeners after DOM is ready
|
||||
if (sendBtn) {
|
||||
sendBtn.onclick = () => {
|
||||
console.log("Send button clicked!");
|
||||
sendMessage();
|
||||
};
|
||||
console.log("sendBtn.onclick attached");
|
||||
} else {
|
||||
console.error("sendBtn element not found!");
|
||||
}
|
||||
|
||||
if (input) {
|
||||
input.addEventListener("keypress", (e) => {
|
||||
console.log("Key pressed:", e.key);
|
||||
if (e.key === "Enter") {
|
||||
console.log("Enter key detected, sending message");
|
||||
sendMessage();
|
||||
}
|
||||
});
|
||||
console.log("input keypress listener attached");
|
||||
} else {
|
||||
console.error("input element not found!");
|
||||
}
|
||||
|
||||
initializeAuth();
|
||||
});
|
||||
window.addEventListener("focus", function () {
|
||||
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
||||
connectWebSocket();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue