chore: remove unused code

This commit is contained in:
Nathan 2025-04-17 11:11:54 +08:00
parent 77fbf0f8a3
commit c633dd0919
19 changed files with 97 additions and 143 deletions

View File

@ -141,6 +141,7 @@ pub trait ChatCloudService: Send + Sync + 'static {
workspace_id: &Uuid,
chat_id: &Uuid,
message_id: i64,
ai_model: Option<AIModel>,
) -> Result<RepeatedRelatedQuestion, FlowyError>;
async fn stream_complete(
@ -158,13 +159,6 @@ pub trait ChatCloudService: Send + Sync + 'static {
metadata: Option<HashMap<String, Value>>,
) -> Result<(), FlowyError>;
async fn get_local_ai_config(&self, workspace_id: &Uuid) -> Result<LocalAIConfig, FlowyError>;
async fn get_workspace_plan(
&self,
workspace_id: &Uuid,
) -> Result<Vec<SubscriptionPlan>, FlowyError>;
async fn get_chat_settings(
&self,
workspace_id: &Uuid,

View File

@ -8,7 +8,6 @@ use crate::middleware::chat_service_mw::AICloudServiceMiddleware;
use crate::persistence::{insert_chat, read_chat_metadata, ChatTable};
use std::collections::HashMap;
use af_plugin::manager::PluginManager;
use dashmap::DashMap;
use flowy_ai_pub::cloud::{
AIModel, ChatCloudService, ChatSettings, UpdateChatParams, DEFAULT_AI_MODEL_NAME,
@ -35,7 +34,6 @@ use uuid::Uuid;
pub trait AIUserService: Send + Sync + 'static {
fn user_id(&self) -> Result<i64, FlowyError>;
fn device_id(&self) -> Result<String, FlowyError>;
fn workspace_id(&self) -> Result<Uuid, FlowyError>;
fn sqlite_connection(&self, uid: i64) -> Result<DBConnection, FlowyError>;
fn application_root_dir(&self) -> Result<PathBuf, FlowyError>;
@ -85,16 +83,9 @@ impl AIManager {
store_preferences: Arc<KVStorePreferences>,
storage_service: Weak<dyn StorageService>,
query_service: impl AIExternalService,
local_ai: Arc<LocalAIController>,
) -> AIManager {
let user_service = Arc::new(user_service);
let plugin_manager = Arc::new(PluginManager::new());
let local_ai = Arc::new(LocalAIController::new(
plugin_manager.clone(),
store_preferences.clone(),
user_service.clone(),
chat_cloud_service.clone(),
));
let cloned_local_ai = local_ai.clone();
tokio::spawn(async move {
cloned_local_ai.observe_plugin_resource().await;
@ -596,7 +587,8 @@ impl AIManager {
message_id: i64,
) -> Result<RepeatedRelatedQuestionPB, FlowyError> {
let chat = self.get_or_create_chat_instance(chat_id).await?;
let resp = chat.get_related_question(message_id).await?;
let ai_model = self.get_active_model(&chat_id.to_string()).await;
let resp = chat.get_related_question(message_id, ai_model).await?;
Ok(resp)
}

View File

@ -524,11 +524,12 @@ impl Chat {
pub async fn get_related_question(
&self,
message_id: i64,
ai_model: Option<AIModel>,
) -> Result<RepeatedRelatedQuestionPB, FlowyError> {
let workspace_id = self.user_service.workspace_id()?;
let resp = self
.chat_service
.get_related_message(&workspace_id, &self.chat_id, message_id)
.get_related_message(&workspace_id, &self.chat_id, message_id, ai_model)
.await?;
trace!(

View File

@ -6,7 +6,7 @@ use crate::notification::{
};
use af_plugin::manager::PluginManager;
use anyhow::Error;
use flowy_ai_pub::cloud::{ChatCloudService, ChatMessageMetadata, ContextLoader, LocalAIConfig};
use flowy_ai_pub::cloud::{ChatMessageMetadata, ContextLoader};
use flowy_error::{FlowyError, FlowyResult};
use flowy_sqlite::kv::KVStorePreferences;
use futures::Sink;
@ -55,8 +55,6 @@ pub struct LocalAIController {
current_chat_id: ArcSwapOption<Uuid>,
store_preferences: Weak<KVStorePreferences>,
user_service: Arc<dyn AIUserService>,
#[allow(dead_code)]
cloud_service: Arc<dyn ChatCloudService>,
}
impl Deref for LocalAIController {
@ -72,7 +70,6 @@ impl LocalAIController {
plugin_manager: Arc<PluginManager>,
store_preferences: Weak<KVStorePreferences>,
user_service: Arc<dyn AIUserService>,
cloud_service: Arc<dyn ChatCloudService>,
) -> Self {
debug!(
"[AI Plugin] init local ai controller, thread: {:?}",
@ -83,7 +80,6 @@ impl LocalAIController {
let local_ai = Arc::new(OllamaAIPlugin::new(plugin_manager));
let res_impl = LLMResourceServiceImpl {
user_service: user_service.clone(),
cloud_service: cloud_service.clone(),
store_preferences: store_preferences.clone(),
};
let local_ai_resource = Arc::new(LocalAIResourceController::new(
@ -160,7 +156,6 @@ impl LocalAIController {
current_chat_id: ArcSwapOption::default(),
store_preferences,
user_service,
cloud_service,
}
}
#[instrument(level = "debug", skip_all)]
@ -379,10 +374,6 @@ impl LocalAIController {
.map(|path| path.to_string_lossy().to_string())
}
pub async fn get_plugin_download_link(&self) -> FlowyResult<String> {
self.resource.get_plugin_download_link().await
}
pub async fn toggle_local_ai(&self) -> FlowyResult<bool> {
let workspace_id = self.user_service.workspace_id()?;
let key = local_ai_enabled_key(&workspace_id);
@ -604,7 +595,6 @@ async fn initialize_ai_plugin(
pub struct LLMResourceServiceImpl {
user_service: Arc<dyn AIUserService>,
cloud_service: Arc<dyn ChatCloudService>,
store_preferences: Weak<KVStorePreferences>,
}
@ -618,15 +608,6 @@ impl LLMResourceServiceImpl {
}
#[async_trait]
impl LLMResourceService for LLMResourceServiceImpl {
async fn fetch_local_ai_config(&self) -> Result<LocalAIConfig, anyhow::Error> {
let workspace_id = self.user_service.workspace_id()?;
let config = self
.cloud_service
.get_local_ai_config(&workspace_id)
.await?;
Ok(config)
}
fn store_setting(&self, setting: LocalAISetting) -> Result<(), Error> {
let store_preferences = self.upgrade_store_preferences()?;
store_preferences.set_object(LOCAL_AI_SETTING_KEY, &setting)?;

View File

@ -1,6 +1,5 @@
use crate::ai_manager::AIUserService;
use crate::local_ai::controller::LocalAISetting;
use flowy_ai_pub::cloud::LocalAIConfig;
use flowy_error::{ErrorCode, FlowyError, FlowyResult};
use lib_infra::async_trait::async_trait;
@ -33,7 +32,6 @@ struct ModelEntry {
#[async_trait]
pub trait LLMResourceService: Send + Sync + 'static {
/// Get local ai configuration from remote server
async fn fetch_local_ai_config(&self) -> Result<LocalAIConfig, anyhow::Error>;
fn store_setting(&self, setting: LocalAISetting) -> Result<(), anyhow::Error>;
fn retrieve_setting(&self) -> Option<LocalAISetting>;
}
@ -125,11 +123,6 @@ impl LocalAIResourceController {
.is_ok_and(|r| r.is_none())
}
pub async fn get_plugin_download_link(&self) -> FlowyResult<String> {
let ai_config = self.get_local_ai_configuration().await?;
Ok(ai_config.plugin.url)
}
/// Retrieves model information and updates the current model settings.
pub fn get_llm_setting(&self) -> LocalAISetting {
self.resource_service.retrieve_setting().unwrap_or_default()
@ -271,19 +264,6 @@ impl LocalAIResourceController {
Ok(config)
}
/// Fetches the local AI configuration from the resource service.
async fn get_local_ai_configuration(&self) -> FlowyResult<LocalAIConfig> {
self
.resource_service
.fetch_local_ai_config()
.await
.map_err(|err| {
error!("[LLM Resource] Failed to fetch local ai config: {:?}", err);
FlowyError::local_ai()
.with_context("Can't retrieve model info. Please try again later".to_string())
})
}
pub(crate) fn user_model_folder(&self) -> FlowyResult<PathBuf> {
self.resource_dir().map(|dir| dir.join(LLM_MODEL_DIR))
}

View File

@ -10,9 +10,9 @@ use std::collections::HashMap;
use flowy_ai_pub::cloud::{
AIModel, AppErrorCode, AppResponseError, ChatCloudService, ChatMessage, ChatMessageMetadata,
ChatMessageType, ChatSettings, CompleteTextParams, CompletionStream, LocalAIConfig,
MessageCursor, ModelList, RelatedQuestion, RepeatedChatMessage, RepeatedRelatedQuestion,
ResponseFormat, StreamAnswer, StreamComplete, SubscriptionPlan, UpdateChatParams,
ChatMessageType, ChatSettings, CompleteTextParams, CompletionStream, MessageCursor, ModelList,
RelatedQuestion, RepeatedChatMessage, RepeatedRelatedQuestion, ResponseFormat, StreamAnswer,
StreamComplete, SubscriptionPlan, UpdateChatParams,
};
use flowy_error::{FlowyError, FlowyResult};
use futures::{stream, Sink, StreamExt, TryStreamExt};
@ -50,10 +50,6 @@ impl AICloudServiceMiddleware {
}
}
pub fn is_local_ai_enabled(&self) -> bool {
self.local_ai.is_enabled()
}
pub async fn index_message_metadata(
&self,
chat_id: &Uuid,
@ -63,7 +59,7 @@ impl AICloudServiceMiddleware {
if metadata_list.is_empty() {
return Ok(());
}
if self.is_local_ai_enabled() {
if self.local_ai.is_enabled() {
let _ = index_process_sink
.send(StreamMessage::IndexStart.to_string())
.await;
@ -262,28 +258,41 @@ impl ChatCloudService for AICloudServiceMiddleware {
workspace_id: &Uuid,
chat_id: &Uuid,
message_id: i64,
ai_model: Option<AIModel>,
) -> Result<RepeatedRelatedQuestion, FlowyError> {
if self.local_ai.is_running() {
let questions = self
.local_ai
.get_related_question(&chat_id.to_string())
.await
.map_err(|err| FlowyError::local_ai().with_context(err))?;
trace!("LocalAI related questions: {:?}", questions);
let use_local_ai = match &ai_model {
None => false,
Some(model) => model.is_local,
};
let items = questions
.into_iter()
.map(|content| RelatedQuestion {
content,
metadata: None,
if use_local_ai {
if self.local_ai.is_running() {
let questions = self
.local_ai
.get_related_question(&chat_id.to_string())
.await
.map_err(|err| FlowyError::local_ai().with_context(err))?;
trace!("LocalAI related questions: {:?}", questions);
let items = questions
.into_iter()
.map(|content| RelatedQuestion {
content,
metadata: None,
})
.collect::<Vec<_>>();
Ok(RepeatedRelatedQuestion { message_id, items })
} else {
Ok(RepeatedRelatedQuestion {
message_id,
items: vec![],
})
.collect::<Vec<_>>();
Ok(RepeatedRelatedQuestion { message_id, items })
}
} else {
self
.cloud_service
.get_related_message(workspace_id, chat_id, message_id)
.get_related_message(workspace_id, chat_id, message_id, ai_model)
.await
}
}
@ -359,10 +368,6 @@ impl ChatCloudService for AICloudServiceMiddleware {
}
}
async fn get_local_ai_config(&self, workspace_id: &Uuid) -> Result<LocalAIConfig, FlowyError> {
self.cloud_service.get_local_ai_config(workspace_id).await
}
async fn get_workspace_plan(
&self,
workspace_id: &Uuid,

View File

@ -6,6 +6,7 @@ use collab::util::is_change_since_sv;
use collab_entity::CollabType;
use collab_integrate::persistence::collab_metadata_sql::AFCollabMetadata;
use flowy_ai::ai_manager::{AIExternalService, AIManager, AIUserService};
use flowy_ai::local_ai::controller::LocalAIController;
use flowy_ai_pub::cloud::ChatCloudService;
use flowy_error::FlowyError;
use flowy_folder::ViewLayout;
@ -33,6 +34,7 @@ impl ChatDepsResolver {
storage_service: Weak<dyn StorageService>,
folder_cloud_service: Arc<dyn FolderCloudService>,
folder_service: impl FolderService,
local_ai: Arc<LocalAIController>,
) -> Arc<AIManager> {
let user_service = ChatUserServiceImpl(authenticate_user);
Arc::new(AIManager::new(
@ -44,6 +46,7 @@ impl ChatDepsResolver {
folder_service: Box::new(folder_service),
folder_cloud_service,
},
local_ai,
))
}
}
@ -166,10 +169,6 @@ impl AIUserService for ChatUserServiceImpl {
self.upgrade_user()?.user_id()
}
fn device_id(&self) -> Result<String, FlowyError> {
self.upgrade_user()?.device_id()
}
fn workspace_id(&self) -> Result<Uuid, FlowyError> {
self.upgrade_user()?.workspace_id()
}

View File

@ -15,8 +15,8 @@ use flowy_ai_pub::cloud::search_dto::{
};
use flowy_ai_pub::cloud::{
AIModel, ChatCloudService, ChatMessage, ChatMessageMetadata, ChatMessageType, ChatSettings,
CompleteTextParams, LocalAIConfig, MessageCursor, ModelList, RepeatedChatMessage, ResponseFormat,
StreamAnswer, StreamComplete, SubscriptionPlan, UpdateChatParams,
CompleteTextParams, MessageCursor, ModelList, RepeatedChatMessage, ResponseFormat, StreamAnswer,
StreamComplete, SubscriptionPlan, UpdateChatParams,
};
use flowy_database_pub::cloud::{
DatabaseAIService, DatabaseCloudService, DatabaseSnapshot, EncodeCollabByOid, SummaryRowContent,
@ -753,11 +753,12 @@ impl ChatCloudService for ServerProvider {
workspace_id: &Uuid,
chat_id: &Uuid,
message_id: i64,
ai_model: Option<AIModel>,
) -> Result<RepeatedRelatedQuestion, FlowyError> {
self
.get_server()?
.chat_service()
.get_related_message(workspace_id, chat_id, message_id)
.get_related_message(workspace_id, chat_id, message_id, ai_model)
.await
}
@ -801,14 +802,6 @@ impl ChatCloudService for ServerProvider {
.await
}
async fn get_local_ai_config(&self, workspace_id: &Uuid) -> Result<LocalAIConfig, FlowyError> {
self
.get_server()?
.chat_service()
.get_local_ai_config(workspace_id)
.await
}
async fn get_workspace_plan(
&self,
workspace_id: &Uuid,

View File

@ -9,6 +9,7 @@ use flowy_folder::manager::FolderManager;
use flowy_search::folder::indexer::FolderIndexManagerImpl;
use flowy_search::services::manager::SearchManager;
use flowy_server::af_cloud::define::ServerUser;
use std::path::PathBuf;
use std::sync::{Arc, Weak};
use std::time::Duration;
use sysinfo::System;
@ -191,6 +192,7 @@ impl AppFlowyCore {
Arc::downgrade(&storage_manager.storage_service),
server_provider.clone(),
folder_query_service.clone(),
server_provider.local_ai.clone(),
);
let database_manager = DatabaseDepsResolver::resolve(
@ -343,4 +345,10 @@ impl ServerUser for ServerUserImpl {
fn get_sqlite_db(&self, uid: i64) -> Result<DBConnection, FlowyError> {
self.upgrade_user()?.get_sqlite_connection(uid)
}
fn application_root_dir(&self) -> Result<PathBuf, FlowyError> {
Ok(PathBuf::from(
self.upgrade_user()?.get_application_root_dir(),
))
}
}

View File

@ -11,11 +11,14 @@ use flowy_server::local_server::LocalServer;
use flowy_server::{AppFlowyEncryption, AppFlowyServer, EncryptionImpl};
use flowy_server_pub::AuthenticatorType;
use flowy_sqlite::kv::KVStorePreferences;
use flowy_sqlite::DBConnection;
use flowy_user_pub::entities::*;
use serde_repr::*;
use std::fmt::{Display, Formatter};
use std::path::PathBuf;
use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
use std::sync::{Arc, Weak};
use uuid::Uuid;
#[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize_repr, Deserialize_repr)]
#[repr(u8)]
@ -59,6 +62,7 @@ pub struct ServerProvider {
authenticator: AtomicU8,
user: Arc<dyn ServerUser>,
pub(crate) uid: Arc<ArcSwapOption<i64>>,
pub local_ai: Arc<LocalAIController>,
}
impl ServerProvider {
@ -66,19 +70,16 @@ impl ServerProvider {
config: AppFlowyCoreConfig,
server: Server,
store_preferences: Weak<KVStorePreferences>,
user_service: impl AIUserService,
server_user: impl ServerUser + 'static,
) -> Self {
let user = Arc::new(server_user);
let encryption = EncryptionImpl::new(None);
let user_service = Arc::new(user_service);
let user_service = Arc::new(AIUserServiceImpl(user.clone()));
let plugin_manager = Arc::new(PluginManager::new());
let local_ai = Arc::new(LocalAIController::new(
plugin_manager.clone(),
store_preferences.clone(),
user_service.clone(),
chat_cloud_service.clone(),
));
Self {
@ -90,6 +91,7 @@ impl ServerProvider {
store_preferences,
uid: Default::default(),
user,
local_ai,
}
}
@ -179,3 +181,23 @@ pub fn current_server_type() -> Server {
AuthenticatorType::AppFlowyCloud => Server::AppFlowyCloud,
}
}
struct AIUserServiceImpl(Arc<dyn ServerUser>);
impl AIUserService for AIUserServiceImpl {
fn user_id(&self) -> Result<i64, FlowyError> {
self.0.user_id()
}
fn workspace_id(&self) -> Result<Uuid, FlowyError> {
self.0.workspace_id()
}
fn sqlite_connection(&self, uid: i64) -> Result<DBConnection, FlowyError> {
self.0.get_sqlite_db(uid)
}
fn application_root_dir(&self) -> Result<PathBuf, FlowyError> {
self.0.application_root_dir()
}
}

View File

@ -1,5 +1,6 @@
use flowy_error::{FlowyError, FlowyResult};
use flowy_sqlite::DBConnection;
use std::path::PathBuf;
use uuid::Uuid;
pub const USER_SIGN_IN_URL: &str = "sign_in_url";
@ -15,4 +16,5 @@ pub trait ServerUser: Send + Sync {
fn user_id(&self) -> FlowyResult<i64>;
fn get_sqlite_db(&self, uid: i64) -> Result<DBConnection, FlowyError>;
fn application_root_dir(&self) -> Result<PathBuf, FlowyError>;
}

View File

@ -9,12 +9,11 @@ use client_api::entity::chat_dto::{
};
use flowy_ai_pub::cloud::{
AIModel, ChatCloudService, ChatMessage, ChatMessageMetadata, ChatMessageType, ChatSettings,
LocalAIConfig, ModelList, StreamAnswer, StreamComplete, SubscriptionPlan, UpdateChatParams,
ModelList, StreamAnswer, StreamComplete, SubscriptionPlan, UpdateChatParams,
};
use flowy_error::FlowyError;
use futures_util::{StreamExt, TryStreamExt};
use lib_infra::async_trait::async_trait;
use lib_infra::util::{get_operating_system, OperatingSystem};
use serde_json::Value;
use std::collections::HashMap;
use std::path::Path;
@ -186,6 +185,7 @@ where
workspace_id: &Uuid,
chat_id: &Uuid,
message_id: i64,
ai_model: Option<AIModel>,
) -> Result<RepeatedRelatedQuestion, FlowyError> {
let try_get_client = self.inner.try_get_client();
let resp = try_get_client?
@ -226,25 +226,6 @@ where
);
}
async fn get_local_ai_config(&self, workspace_id: &Uuid) -> Result<LocalAIConfig, FlowyError> {
let system = get_operating_system();
let platform = match system {
OperatingSystem::MacOS => "macos",
_ => {
return Err(
FlowyError::not_support()
.with_context("local ai is not supported on this operating system"),
);
},
};
let config = self
.inner
.try_get_client()?
.get_local_ai_config(workspace_id.to_string().as_str(), platform)
.await?;
Ok(config)
}
async fn get_workspace_plan(
&self,
workspace_id: &Uuid,

View File

@ -1,5 +1,5 @@
use crate::af_cloud::define::ServerUser;
use client_api::entity::ai_dto::{LocalAIConfig, RepeatedRelatedQuestion};
use client_api::entity::ai_dto::RepeatedRelatedQuestion;
use flowy_ai_pub::cloud::{
AIModel, ChatCloudService, ChatMessage, ChatMessageMetadata, ChatMessageType, ChatSettings,
CompleteTextParams, MessageCursor, ModelList, RepeatedChatMessage, ResponseFormat, StreamAnswer,
@ -98,6 +98,7 @@ impl ChatCloudService for LocalServerChatServiceImpl {
_workspace_id: &Uuid,
_chat_id: &Uuid,
message_id: i64,
ai_model: Option<AIModel>,
) -> Result<RepeatedRelatedQuestion, FlowyError> {
Ok(RepeatedRelatedQuestion {
message_id,
@ -133,13 +134,6 @@ impl ChatCloudService for LocalServerChatServiceImpl {
Err(FlowyError::not_support().with_context("indexing file is not supported in local server."))
}
async fn get_local_ai_config(&self, _workspace_id: &Uuid) -> Result<LocalAIConfig, FlowyError> {
Err(
FlowyError::not_support()
.with_context("Get local ai config is not supported in local server."),
)
}
async fn get_workspace_plan(
&self,
_workspace_id: &Uuid,

View File

@ -1,5 +1,4 @@
#![allow(unused_variables)]
use std::sync::Arc;
use client_api::entity::workspace_dto::PublishInfoView;
use client_api::entity::PublishInfo;

View File

@ -5,7 +5,6 @@ use collab::preclude::Collab;
use collab_entity::CollabObject;
use collab_user::core::UserAwareness;
use lazy_static::lazy_static;
use std::sync::Arc;
use tokio::sync::Mutex;
use uuid::Uuid;

View File

@ -1,6 +1,7 @@
use client_api::ClientConfiguration;
use semver::Version;
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::Arc;
use flowy_error::{FlowyError, FlowyResult};
@ -50,6 +51,10 @@ impl ServerUser for FakeServerUserImpl {
fn get_sqlite_db(&self, uid: i64) -> Result<DBConnection, FlowyError> {
todo!()
}
fn application_root_dir(&self) -> Result<PathBuf, FlowyError> {
todo!()
}
}
pub async fn generate_sign_in_url(user_email: &str, config: &AFCloudConfiguration) -> String {

View File

@ -14,7 +14,7 @@ use flowy_user_pub::session::Session;
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::{Arc, Weak};
use tracing::{error, info};
use tracing::info;
use uuid::Uuid;
pub struct AuthenticateUser {

View File

@ -1,5 +1,5 @@
use diesel::{sql_query, RunQueryDsl};
use flowy_error::{internal_error, FlowyError};
use diesel::RunQueryDsl;
use flowy_error::FlowyError;
use std::str::FromStr;
use flowy_user_pub::cloud::UserUpdate;

View File

@ -6,7 +6,6 @@ use std::convert::TryFrom;
use std::str::FromStr;
use std::sync::Arc;
use collab_entity::{CollabObject, CollabType};
use collab_integrate::CollabKVDB;
use flowy_error::{ErrorCode, FlowyError, FlowyResult};
use flowy_folder_pub::entities::{ImportFrom, ImportedCollabData, ImportedFolderData};
@ -20,7 +19,7 @@ use tracing::{error, info, instrument, trace, warn};
use uuid::Uuid;
use crate::entities::{
RepeatedUserWorkspacePB, ResetWorkspacePB, SubscribeWorkspacePB, SuccessWorkspaceSubscriptionPB,
RepeatedUserWorkspacePB, SubscribeWorkspacePB, SuccessWorkspaceSubscriptionPB,
UpdateUserWorkspaceSettingPB, UseAISettingPB, UserWorkspacePB, WorkspaceSubscriptionInfoPB,
};
use crate::migrations::AnonUser;
@ -575,7 +574,7 @@ impl UserManager {
if let Ok(member_record) = select_workspace_member(db, &workspace_id.to_string(), uid) {
if is_older_than_n_minutes(member_record.updated_at, 10) {
self
.get_workspace_member_info_from_remote(&workspace_id, uid)
.get_workspace_member_info_from_remote(workspace_id, uid)
.await?;
}