diff --git a/moly-mofa/src/lib.rs b/moly-mofa/src/lib.rs index 28bb5520..7f19156b 100644 --- a/moly-mofa/src/lib.rs +++ b/moly-mofa/src/lib.rs @@ -4,6 +4,7 @@ use moly_protocol::open_ai::{ use serde::{Deserialize, Deserializer, Serialize}; use std::sync::mpsc::{self, channel, Sender}; use tokio::task::JoinHandle; +use serde_json::Value; #[derive(Debug, Serialize, Deserialize)] pub struct MofaResponseReasoner { @@ -105,6 +106,13 @@ pub enum MofaAgentCommand { FetchAgentsFromServer(Sender), } +#[derive(Debug, Serialize, Deserialize)] +struct MofaContent { + step_name: String, + node_results: String, + dataflow_status: bool, +} + #[derive(Clone, Debug)] pub struct MofaClient { command_sender: Sender, @@ -176,23 +184,86 @@ impl MofaClient { content: task, }], }; - let client = reqwest::Client::new(); + + // If access to OpenAI or Claude is restricted in certain regions, a VPN is typically used, + // so communication with the local MoFA service here must bypass the proxy. + let client = reqwest::Client::builder() + .no_proxy() + .build() + .expect("Failed to build client"); let req = client .post(format!("{}/v1/chat/completions", &address)) + .header("Content-Type", "application/json") .json(&data); current_request = Some(rt.spawn(async move { - let resp = req.send().await.expect("Failed to send request"); - - let resp: Result = resp.json().await; - match resp { - Ok(resp) => { - let _ = tx.send(ChatResponse::ChatFinalResponseData(resp.clone())); - } - Err(e) => { - eprintln!("{e}"); + match req.send().await { + Ok(response) => { + if response.status().is_success() { + match response.text().await { + Ok(text) => { + match serde_json::from_str::(&text) { + Ok(value) => { + if let Some(content) = value + .get("choices") + .and_then(|choices| choices.get(0)) + .and_then(|choice| choice.get("message")) + .and_then(|message| message.get("content")) + .and_then(|content| content.as_str()) + { + // parsing inner json + match serde_json::from_str::(content) { + Ok(mofa_content) => { + let response_data = ChatResponseData { + id: value.get("id").and_then(|id| id.as_str()).unwrap_or("").to_string(), + choices: vec![ChoiceData { + finish_reason: StopReason::Stop, + index: 0, + message: MessageData { + content: mofa_content.node_results, + role: Role::Assistant, + }, + logprobs: None, + }], + created: value.get("created") + .and_then(|c| c.as_i64()) + .unwrap_or(0), + model: value.get("model").and_then(|m| m.as_str()).unwrap_or("").to_string(), + system_fingerprint: "".to_string(), + usage: UsageData { + completion_tokens: 0, + prompt_tokens: 0, + total_tokens: 0, + }, + object: value.get("object").and_then(|o| o.as_str()).unwrap_or("").to_string(), + }; + + let _ = tx.send(ChatResponse::ChatFinalResponseData(response_data)); + } + Err(e) => { + eprintln!("Failed to parse content JSON: {}", e); + eprintln!("Content: {}", content); + } + } + } + } + Err(e) => { + eprintln!("Failed to parse response JSON: {}", e); + eprintln!("Response: {}", text); + } + } + } + Err(e) => eprintln!("Failed to get response text: {}", e), + } + } else { + eprintln!("HTTP error: {}", response.status()); + if let Ok(error_text) = response.text().await { + eprintln!("Error details: {}", error_text); + } + } } + Err(e) => eprintln!("Request failed: {}", e), } })); } @@ -254,7 +325,6 @@ impl MofaClient { fn new_fake(address: String) -> Self { let (command_sender, command_receiver) = channel(); - let address_clone = address.clone(); std::thread::spawn(move || { while let Ok(command) = command_receiver.recv() { diff --git a/moly-protocol/src/open_ai.rs b/moly-protocol/src/open_ai.rs index cad63d11..15fb55aa 100644 --- a/moly-protocol/src/open_ai.rs +++ b/moly-protocol/src/open_ai.rs @@ -107,7 +107,7 @@ pub struct UsageData { pub struct ChatResponseData { pub id: String, pub choices: Vec, - pub created: u32, + pub created: i64, pub model: ModelID, #[serde(default)] pub system_fingerprint: String, diff --git a/src/data/chats/chat.rs b/src/data/chats/chat.rs index 0891246a..74ea8601 100644 --- a/src/data/chats/chat.rs +++ b/src/data/chats/chat.rs @@ -428,11 +428,12 @@ impl Chat { std::thread::spawn(move || '_loop: loop { match rx.recv() { Ok(moly_mofa::ChatResponse::ChatFinalResponseData(data)) => { - let node_results = serde_json::from_str::(&data.choices[0].message.content).unwrap(); + // The original JSON data of node_results has been parsed and can be used directly. + let node_results = data.choices[0].clone().message.content; Cx::post_action(ChatEntityAction { chat_id, kind: ChatEntityActionKind::MofaAgentResult( - node_results.node_results + node_results ), }); diff --git a/src/data/store.rs b/src/data/store.rs index 6fb1f472..01ab0afd 100644 --- a/src/data/store.rs +++ b/src/data/store.rs @@ -11,7 +11,6 @@ use anyhow::Result; use chrono::{DateTime, Utc}; use makepad_widgets::{Action, ActionDefaultRef, DefaultNone}; use moly_backend::Backend; - use moly_mofa::MofaServerResponse; use moly_protocol::data::{Author, DownloadedFile, File, FileID, Model, ModelID, PendingDownload}; use std::rc::Rc;