fix: show only enabled datasource & MCP list (#523)

* fix: show only enabled datasource & MCP list

* docs: update notes

* fix: show only enabled datasource & MCP list
This commit is contained in:
BiggerRain
2025-05-17 12:01:18 +08:00
committed by GitHub
parent 7f3e602bb3
commit 91c9cd5725
8 changed files with 132 additions and 115 deletions

View File

@@ -13,6 +13,7 @@
"elif", "elif",
"errmsg", "errmsg",
"fullscreen", "fullscreen",
"fulltext",
"headlessui", "headlessui",
"Icdbb", "Icdbb",
"icns", "icns",

View File

@@ -32,6 +32,7 @@ Information about release notes of Coco Server is provided here.
- fix: fixed the newly created session has no title when it is deleted #511 - fix: fixed the newly created session has no title when it is deleted #511
- fix: loading chat history for potential empty attachments - fix: loading chat history for potential empty attachments
- fix: datasource & MCP list synchronization update #521 - fix: datasource & MCP list synchronization update #521
- fix: show only enabled datasource & MCP list
### ✈️ Improvements ### ✈️ Improvements

View File

@@ -26,7 +26,7 @@ pub async fn get_response_body_text(response: Response) -> Result<String, String
.await .await
.map_err(|e| format!("Failed to read response body: {}, code: {}", e, status))?; .map_err(|e| format!("Failed to read response body: {}, code: {}", e, status))?;
log::debug!("Response status: {}, body: {}", status, &body); //log::debug!("Response status: {}, body: {}", status, &body);
if status < 200 || status >= 400 { if status < 200 || status >= 400 {
// Try to parse the error body // Try to parse the error body

View File

@@ -210,7 +210,7 @@ pub fn run() {
}) })
.on_window_event(|window, event| match event { .on_window_event(|window, event| match event {
WindowEvent::CloseRequested { api, .. } => { WindowEvent::CloseRequested { api, .. } => {
dbg!("Close requested event received"); //dbg!("Close requested event received");
window.hide().unwrap(); window.hide().unwrap();
api.prevent_close(); api.prevent_close();
} }
@@ -225,10 +225,10 @@ pub fn run() {
has_visible_windows, has_visible_windows,
.. ..
} => { } => {
dbg!( // dbg!(
"Reopen event received: has_visible_windows = {}", // "Reopen event received: has_visible_windows = {}",
has_visible_windows // has_visible_windows
); // );
if has_visible_windows { if has_visible_windows {
return; return;
} }
@@ -289,7 +289,7 @@ async fn hide_coco<R: Runtime>(app: AppHandle<R>) {
} }
fn move_window_to_active_monitor<R: Runtime>(window: &Window<R>) { fn move_window_to_active_monitor<R: Runtime>(window: &Window<R>) {
dbg!("Moving window to active monitor"); //dbg!("Moving window to active monitor");
// Try to get the available monitors, handle failure gracefully // Try to get the available monitors, handle failure gracefully
let available_monitors = match window.available_monitors() { let available_monitors = match window.available_monitors() {
Ok(monitors) => monitors, Ok(monitors) => monitors,

View File

@@ -4,6 +4,7 @@ use crate::server::connector::get_connector_by_id;
use crate::server::http_client::HttpClient; use crate::server::http_client::HttpClient;
use crate::server::servers::get_all_servers; use crate::server::servers::get_all_servers;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use serde_json::Value;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use tauri::{AppHandle, Runtime}; use tauri::{AppHandle, Runtime};
@@ -12,7 +13,7 @@ use tauri::{AppHandle, Runtime};
pub struct GetDatasourcesByServerOptions { pub struct GetDatasourcesByServerOptions {
pub from: Option<u32>, pub from: Option<u32>,
pub size: Option<u32>, pub size: Option<u32>,
pub query: Option<String>, pub query: Option<serde_json::Value>,
} }
lazy_static! { lazy_static! {
@@ -100,31 +101,14 @@ pub async fn datasource_search(
) -> Result<Vec<DataSource>, String> { ) -> Result<Vec<DataSource>, String> {
let from = options.as_ref().and_then(|opt| opt.from).unwrap_or(0); let from = options.as_ref().and_then(|opt| opt.from).unwrap_or(0);
let size = options.as_ref().and_then(|opt| opt.size).unwrap_or(10000); let size = options.as_ref().and_then(|opt| opt.size).unwrap_or(10000);
let query = options
.and_then(|opt| opt.query)
.unwrap_or(String::default());
let mut body = serde_json::json!({ let mut body = serde_json::json!({
"from": from, "from": from,
"size": size, "size": size,
}); });
if !query.is_empty() { if let Some(q) = options.unwrap().query {
body["query"] = serde_json::json!({ body["query"] = q;
"bool": {
"must": [{
"query_string": {
"fields": ["combined_fulltext"],
"query": query,
"fuzziness": "AUTO",
"fuzzy_prefix_length": 2,
"fuzzy_max_expansions": 10,
"fuzzy_transpositions": true,
"allow_leading_wildcard": false
}
}]
}
});
} }
// Perform the async HTTP request outside the cache lock // Perform the async HTTP request outside the cache lock
@@ -139,7 +123,7 @@ pub async fn datasource_search(
// Parse the search results from the response // Parse the search results from the response
let datasources: Vec<DataSource> = parse_search_results(resp).await.map_err(|e| { let datasources: Vec<DataSource> = parse_search_results(resp).await.map_err(|e| {
dbg!("Error parsing search results: {}", &e); //dbg!("Error parsing search results: {}", &e);
e.to_string() e.to_string()
})?; })?;
@@ -152,35 +136,17 @@ pub async fn datasource_search(
#[tauri::command] #[tauri::command]
pub async fn mcp_server_search( pub async fn mcp_server_search(
id: &str, id: &str,
options: Option<GetDatasourcesByServerOptions>, from: u32,
size: u32,
query: Option<HashMap<String, Value>>,
) -> Result<Vec<DataSource>, String> { ) -> Result<Vec<DataSource>, String> {
let from = options.as_ref().and_then(|opt| opt.from).unwrap_or(0);
let size = options.as_ref().and_then(|opt| opt.size).unwrap_or(10000);
let query = options
.and_then(|opt| opt.query)
.unwrap_or(String::default());
let mut body = serde_json::json!({ let mut body = serde_json::json!({
"from": from, "from": from,
"size": size, "size": size,
}); });
if !query.is_empty() { if let Some(q) = query {
body["query"] = serde_json::json!({ body["query"] = serde_json::to_value(q).map_err(|e| e.to_string())?;
"bool": {
"must": [{
"query_string": {
"fields": ["combined_fulltext"],
"query": query,
"fuzziness": "AUTO",
"fuzzy_prefix_length": 2,
"fuzzy_max_expansions": 10,
"fuzzy_transpositions": true,
"allow_leading_wildcard": false
}
}]
}
});
} }
// Perform the async HTTP request outside the cache lock // Perform the async HTTP request outside the cache lock
@@ -195,7 +161,7 @@ pub async fn mcp_server_search(
// Parse the search results from the response // Parse the search results from the response
let mcp_server: Vec<DataSource> = parse_search_results(resp).await.map_err(|e| { let mcp_server: Vec<DataSource> = parse_search_results(resp).await.map_err(|e| {
dbg!("Error parsing search results: {}", &e); //dbg!("Error parsing search results: {}", &e);
e.to_string() e.to_string()
})?; })?;

View File

@@ -44,28 +44,28 @@ impl HttpClient {
headers: Option<HashMap<String, String>>, headers: Option<HashMap<String, String>>,
body: Option<reqwest::Body>, body: Option<reqwest::Body>,
) -> Result<reqwest::Response, String> { ) -> Result<reqwest::Response, String> {
log::debug!( // log::debug!(
"Sending Request: {}, query_params: {:?}, header: {:?}, body: {:?}", // "Sending Request: {}, query_params: {:?}, header: {:?}, body: {:?}",
&url, // &url,
&query_params, // &query_params,
&headers, // &headers,
&body // &body
); // );
let request_builder = let request_builder =
Self::get_request_builder(method, url, headers, query_params, body).await; Self::get_request_builder(method, url, headers, query_params, body).await;
let response = request_builder.send().await.map_err(|e| { let response = request_builder.send().await.map_err(|e| {
dbg!("Failed to send request: {}", &e); //dbg!("Failed to send request: {}", &e);
format!("Failed to send request: {}", e) format!("Failed to send request: {}", e)
})?; })?;
log::debug!( // log::debug!(
"Request: {}, Response status: {:?}, header: {:?}", // "Request: {}, Response status: {:?}, header: {:?}",
&url, // &url,
&response.status(), // &response.status(),
&response.headers() // &response.headers()
); // );
Ok(response) Ok(response)
} }
@@ -165,12 +165,12 @@ impl HttpClient {
headers.insert("X-API-TOKEN".to_string(), t); headers.insert("X-API-TOKEN".to_string(), t);
} }
log::debug!( // log::debug!(
"Sending request to server: {}, url: {}, headers: {:?}", // "Sending request to server: {}, url: {}, headers: {:?}",
&server_id, // &server_id,
&url, // &url,
&headers // &headers
); // );
Self::send_raw_request(method, &url, query_params, Some(headers), body).await Self::send_raw_request(method, &url, query_params, Some(headers), body).await
} else { } else {

View File

@@ -82,14 +82,12 @@ export function AssistantList({ assistantIDs = [] }: AssistantListProps) {
size, size,
}; };
if (debounceKeyword || assistantIDs.length > 0) {
body.query = { body.query = {
bool: { bool: {
must: [ must: [{ term: { enabled: true } }],
{term: {"enabled": true}}
],
}, },
}; };
if (debounceKeyword) { if (debounceKeyword) {
body.query.bool.must.push({ body.query.bool.must.push({
query_string: { query_string: {
@@ -110,7 +108,6 @@ export function AssistantList({ assistantIDs = [] }: AssistantListProps) {
}, },
}); });
} }
}
if (isTauri) { if (isTauri) {
if (!currentServiceId) { if (!currentServiceId) {

View File

@@ -23,7 +23,7 @@ import platformAdapter from "@/utils/platformAdapter";
import { useStartupStore } from "@/stores/startupStore"; import { useStartupStore } from "@/stores/startupStore";
import { DataSource } from "@/types/commands"; import { DataSource } from "@/types/commands";
import { useThemeStore } from "@/stores/themeStore"; import { useThemeStore } from "@/stores/themeStore";
import { Get } from "@/api/axiosRequest"; import { Post } from "@/api/axiosRequest";
import { useConnectStore } from "@/stores/connectStore"; import { useConnectStore } from "@/stores/connectStore";
import { useAppearanceStore } from "@/stores/appearanceStore"; import { useAppearanceStore } from "@/stores/appearanceStore";
@@ -217,14 +217,41 @@ function SearchChat({
) { ) {
return []; return [];
} }
const body: Record<string, any> = {
id: serverId,
from: options?.from || 0,
size: options?.size || 1000,
};
body.query = {
bool: {
must: [{ term: { enabled: true } }],
},
};
if (options?.query) {
body.query.bool.must.push({
query_string: {
fields: ["combined_fulltext"],
query: options?.query,
fuzziness: "AUTO",
fuzzy_prefix_length: 2,
fuzzy_max_expansions: 10,
fuzzy_transpositions: true,
allow_leading_wildcard: false,
},
});
}
let response: any; let response: any;
if (isTauri) { if (isTauri) {
response = await platformAdapter.invokeBackend("datasource_search", { response = await platformAdapter.invokeBackend("datasource_search", {
id: serverId, id: serverId,
options, options: body,
}); });
} else { } else {
const [error, res]: any = await Get("/datasource/_search"); const [error, res]: any = await Post("/datasource/_search", body);
if (error) { if (error) {
console.error("_search", error); console.error("_search", error);
return []; return [];
@@ -258,14 +285,39 @@ function SearchChat({
if (!(assistantConfig.mcpEnabled && assistantConfig.mcpVisible)) { if (!(assistantConfig.mcpEnabled && assistantConfig.mcpVisible)) {
return []; return [];
} }
const body: Record<string, any> = {
id: serverId,
from: options?.from || 0,
size: options?.size || 1000,
};
body.query = {
bool: {
must: [{ term: { enabled: true } }],
},
};
if (options?.query) {
body.query.bool.must.push({
query_string: {
fields: ["combined_fulltext"],
query: options?.query,
fuzziness: "AUTO",
fuzzy_prefix_length: 2,
fuzzy_max_expansions: 10,
fuzzy_transpositions: true,
allow_leading_wildcard: false,
},
});
}
let response: any; let response: any;
if (isTauri) { if (isTauri) {
response = await platformAdapter.invokeBackend("mcp_server_search", { response = await platformAdapter.invokeBackend(
id: serverId, "mcp_server_search",
options, body
}); );
} else { } else {
const [error, res]: any = await Get("/mcp_server/_search"); const [error, res]: any = await Post("/mcp_server/_search", body);
if (error) { if (error) {
console.error("_search", error); console.error("_search", error);
return []; return [];