From c6ad57f11d04ba58b147c7e106e147c732062827 Mon Sep 17 00:00:00 2001 From: "Nathan.fooo" <86001920+appflowy@users.noreply.github.com> Date: Mon, 15 Jul 2024 22:45:53 +0800 Subject: [PATCH] chore: show plugin state (#5740) * chore: show plugin state * chore: flutter analyzer * chore: update --- .../shared/auth_operation.dart | 1 - .../ai_chat/application/chat_file_bloc.dart | 43 ++++++++- .../lib/plugins/ai_chat/chat_page.dart | 31 ++++--- .../settings/ai/local_ai_bloc.dart | 14 ++- .../settings/ai/local_llm_listener.dart | 4 +- .../settings/ai/plugin_state_bloc.dart | 72 ++++++++++++--- .../pages/setting_ai_view/plugin_state.dart | 88 ++++++++++++++++--- frontend/appflowy_tauri/src-tauri/Cargo.lock | 4 +- frontend/appflowy_tauri/src-tauri/Cargo.toml | 4 +- .../appflowy_web_app/src-tauri/Cargo.lock | 4 +- .../appflowy_web_app/src-tauri/Cargo.toml | 4 +- frontend/resources/translations/en.json | 2 + frontend/rust-lib/Cargo.lock | 4 +- frontend/rust-lib/Cargo.toml | 4 +- .../rust-lib/flowy-chat/src/event_handler.rs | 9 ++ frontend/rust-lib/flowy-chat/src/event_map.rs | 4 + .../flowy-chat/src/local_ai/local_llm_chat.rs | 14 ++- 17 files changed, 251 insertions(+), 55 deletions(-) diff --git a/frontend/appflowy_flutter/integration_test/shared/auth_operation.dart b/frontend/appflowy_flutter/integration_test/shared/auth_operation.dart index 9c103ace86..e2c926fcfe 100644 --- a/frontend/appflowy_flutter/integration_test/shared/auth_operation.dart +++ b/frontend/appflowy_flutter/integration_test/shared/auth_operation.dart @@ -15,7 +15,6 @@ extension AppFlowyAuthTest on WidgetTester { Future tapGoogleLoginInButton() async { await tapButton( find.byKey(const Key('signInWithGoogleButton')), - milliseconds: 3000, ); } diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_file_bloc.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_file_bloc.dart index 7f81dbcb53..859d969927 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_file_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_file_bloc.dart @@ -1,3 +1,4 @@ +import 'package:appflowy/workspace/application/settings/ai/local_llm_listener.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-chat/entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -9,31 +10,69 @@ class ChatFileBloc extends Bloc { ChatFileBloc({ required String chatId, dynamic message, - }) : super(ChatFileState.initial(message)) { + }) : listener = LocalLLMListener(), + super(ChatFileState.initial(message)) { + listener.start( + stateCallback: (pluginState) { + if (!isClosed) { + add(ChatFileEvent.updateLocalAIState(pluginState)); + } + }, + ); + on( (event, emit) async { await event.when( - initial: () async {}, + initial: () async { + final result = await ChatEventGetPluginState().send(); + result.fold( + (pluginState) { + if (!isClosed) { + add(ChatFileEvent.updateLocalAIState(pluginState)); + } + }, + (err) {}, + ); + }, newFile: (String filePath) { final payload = ChatFilePB(filePath: filePath, chatId: chatId); ChatEventChatWithFile(payload).send(); }, + updateLocalAIState: (PluginStatePB pluginState) { + emit( + state.copyWith( + supportChatWithFile: + pluginState.state == RunningStatePB.Running, + ), + ); + }, ); }, ); } + + final LocalLLMListener listener; + + @override + Future close() async { + await listener.stop(); + return super.close(); + } } @freezed class ChatFileEvent with _$ChatFileEvent { const factory ChatFileEvent.initial() = Initial; const factory ChatFileEvent.newFile(String filePath) = _NewFile; + const factory ChatFileEvent.updateLocalAIState(PluginStatePB pluginState) = + _UpdateLocalAIState; } @freezed class ChatFileState with _$ChatFileState { const factory ChatFileState({ required String text, + @Default(false) bool supportChatWithFile, }) = _ChatFileState; factory ChatFileState.initial(dynamic text) { diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index 9c6a0eda0e..77d9e25547 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -71,19 +71,24 @@ class AIChatPage extends StatelessWidget { create: (context) => ChatFileBloc(chatId: view.id.toString()), child: BlocBuilder( builder: (context, state) { - return DropTarget( - onDragDone: (DropDoneDetails detail) async { - for (final file in detail.files) { - context - .read() - .add(ChatFileEvent.newFile(file.path)); - } - }, - child: _ChatContentPage( - view: view, - userProfile: userProfile, - ), - ); + return state.supportChatWithFile + ? DropTarget( + onDragDone: (DropDoneDetails detail) async { + for (final file in detail.files) { + context + .read() + .add(ChatFileEvent.newFile(file.path)); + } + }, + child: _ChatContentPage( + view: view, + userProfile: userProfile, + ), + ) + : _ChatContentPage( + view: view, + userProfile: userProfile, + ); }, ), ); diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/ai/local_ai_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/ai/local_ai_bloc.dart index 15d91d6b96..c6306cd274 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/ai/local_ai_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/ai/local_ai_bloc.dart @@ -20,7 +20,7 @@ class LocalAISettingBloc listener.start( stateCallback: (newState) { if (!isClosed) { - add(LocalAISettingEvent.updateLLMRunningState(newState)); + add(LocalAISettingEvent.updateLLMRunningState(newState.state)); } }, ); @@ -51,7 +51,11 @@ class LocalAISettingBloc ); }, (err) { - emit(state.copyWith(fetchModelInfoState: LoadingState.finish(error: err))); + emit( + state.copyWith( + fetchModelInfoState: LoadingState.finish(error: err), + ), + ); }, ); }, @@ -184,6 +188,12 @@ class LocalAISettingBloc add(LocalAISettingEvent.didLoadModelInfo(result)); } } + + @override + Future close() async { + await listener.stop(); + return super.close(); + } } @freezed diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/ai/local_llm_listener.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/ai/local_llm_listener.dart index f68d14abed..b89fc0ad1a 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/ai/local_llm_listener.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/ai/local_llm_listener.dart @@ -9,7 +9,7 @@ import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart'; import 'package:appflowy_backend/rust_stream.dart'; import 'package:appflowy_result/appflowy_result.dart'; -typedef PluginStateCallback = void Function(RunningStatePB state); +typedef PluginStateCallback = void Function(PluginStatePB state); class LocalLLMListener { LocalLLMListener() { @@ -39,7 +39,7 @@ class LocalLLMListener { result.map((r) { switch (ty) { case ChatNotification.UpdateChatPluginState: - stateCallback?.call(PluginStatePB.fromBuffer(r).state); + stateCallback?.call(PluginStatePB.fromBuffer(r)); break; default: break; diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/ai/plugin_state_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/ai/plugin_state_bloc.dart index e4f61b8e99..018e7fcb69 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/ai/plugin_state_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/ai/plugin_state_bloc.dart @@ -1,24 +1,67 @@ import 'dart:async'; +import 'package:appflowy/workspace/application/settings/ai/local_llm_listener.dart'; +import 'package:appflowy_backend/dispatch/dispatch.dart'; +import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-chat/entities.pb.dart'; import 'package:bloc/bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'plugin_state_bloc.freezed.dart'; -class PluginStateBloc extends Bloc { +class PluginStateBloc extends Bloc { PluginStateBloc() - : super( - const PluginState(runningState: RunningStatePB.Connecting), - ) { + : listener = LocalLLMListener(), + super(const PluginStateState(action: PluginStateAction.init())) { + listener.start( + stateCallback: (pluginState) { + if (!isClosed) { + add(PluginStateEvent.updateState(pluginState)); + } + }, + ); + on(_handleEvent); } + final LocalLLMListener listener; + + @override + Future close() async { + await listener.stop(); + return super.close(); + } + Future _handleEvent( PluginStateEvent event, - Emitter emit, + Emitter emit, ) async { await event.when( - started: () async {}, + started: () async { + final result = await ChatEventGetPluginState().send(); + result.fold( + (pluginState) { + if (!isClosed) { + add(PluginStateEvent.updateState(pluginState)); + } + }, + (err) => Log.error(err.toString()), + ); + }, + updateState: (PluginStatePB pluginState) { + switch (pluginState.state) { + case RunningStatePB.Running: + emit(const PluginStateState(action: PluginStateAction.ready())); + break; + default: + emit( + state.copyWith(action: const PluginStateAction.reloadRequired()), + ); + break; + } + }, + restartLocalAI: () { + ChatEventRestartLocalAI().send(); + }, ); } } @@ -26,11 +69,20 @@ class PluginStateBloc extends Bloc { @freezed class PluginStateEvent with _$PluginStateEvent { const factory PluginStateEvent.started() = _Started; + const factory PluginStateEvent.updateState(PluginStatePB pluginState) = + _UpdatePluginState; + const factory PluginStateEvent.restartLocalAI() = _RestartLocalAI; } @freezed -class PluginState with _$PluginState { - const factory PluginState({ - required RunningStatePB runningState, - }) = _PluginState; +class PluginStateState with _$PluginStateState { + const factory PluginStateState({required PluginStateAction action}) = + _PluginStateState; +} + +@freezed +class PluginStateAction with _$PluginStateAction { + const factory PluginStateAction.init() = _Init; + const factory PluginStateAction.ready() = _Ready; + const factory PluginStateAction.reloadRequired() = _ReloadRequired; } diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/setting_ai_view/plugin_state.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/setting_ai_view/plugin_state.dart index 66c000b892..1081f6aa65 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/setting_ai_view/plugin_state.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/setting_ai_view/plugin_state.dart @@ -2,9 +2,10 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/workspace/application/settings/ai/plugin_state_bloc.dart'; import 'package:easy_localization/easy_localization.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flutter/widgets.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class CheckPluginStateIndicator extends StatelessWidget { @@ -12,17 +13,82 @@ class CheckPluginStateIndicator extends StatelessWidget { @override Widget build(BuildContext context) { - return DecoratedBox( - decoration: const BoxDecoration( - color: Color(0xFFEDF7ED), - borderRadius: BorderRadius.all( - Radius.circular(4), - ), + return BlocProvider( + create: (context) => + PluginStateBloc()..add(const PluginStateEvent.started()), + child: BlocBuilder( + builder: (context, state) { + return state.action.when( + init: () => const _InitPlugin(), + ready: () => const _ReadyToUse(), + reloadRequired: () => const _ReloadButton(), + ); + }, ), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4), - child: BlocProvider( - create: (context) => PluginStateBloc(), + ); + } +} + +class _InitPlugin extends StatelessWidget { + const _InitPlugin(); + + @override + Widget build(BuildContext context) { + return const SizedBox( + height: 20, + child: CircularProgressIndicator.adaptive(), + ); + } +} + +class _ReloadButton extends StatelessWidget { + const _ReloadButton(); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + const FlowySvg( + FlowySvgs.download_warn_s, + color: Color(0xFFC62828), + ), + const HSpace(6), + FlowyText(LocaleKeys.settings_aiPage_keys_failToLoadLocalAI.tr()), + const Spacer(), + SizedBox( + height: 30, + child: FlowyButton( + useIntrinsicWidth: true, + text: + FlowyText(LocaleKeys.settings_aiPage_keys_restartLocalAI.tr()), + onTap: () { + context.read().add( + const PluginStateEvent.restartLocalAI(), + ); + }, + ), + ), + ], + ); + } +} + +class _ReadyToUse extends StatelessWidget { + const _ReadyToUse(); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4), + child: DecoratedBox( + decoration: const BoxDecoration( + color: Color(0xFFEDF7ED), + borderRadius: BorderRadius.all( + Radius.circular(4), + ), + ), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 6), child: Row( children: [ const HSpace(8), diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index c77572fcac..30fcf05a18 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -206,7 +206,7 @@ dependencies = [ [[package]] name = "appflowy-local-ai" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-LocalAI?rev=b803d8a8fd6b1587449e869b3a7a1ac687cf630b#b803d8a8fd6b1587449e869b3a7a1ac687cf630b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-LocalAI?rev=346020270a0a3d3c82a60b545cd3f52144d56beb#346020270a0a3d3c82a60b545cd3f52144d56beb" dependencies = [ "anyhow", "appflowy-plugin", @@ -225,7 +225,7 @@ dependencies = [ [[package]] name = "appflowy-plugin" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-LocalAI?rev=b803d8a8fd6b1587449e869b3a7a1ac687cf630b#b803d8a8fd6b1587449e869b3a7a1ac687cf630b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-LocalAI?rev=346020270a0a3d3c82a60b545cd3f52144d56beb#346020270a0a3d3c82a60b545cd3f52144d56beb" dependencies = [ "anyhow", "cfg-if", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index 8ba790b3a9..4c4a5ff585 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -128,5 +128,5 @@ collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy- # To update the commit ID, run: # scripts/tool/update_local_ai_rev.sh new_rev_id # ⚠️⚠️⚠️️ -appflowy-local-ai = { version = "0.1", git = "https://github.com/AppFlowy-IO/AppFlowy-LocalAI", rev = "b803d8a8fd6b1587449e869b3a7a1ac687cf630b" } -appflowy-plugin = { version = "0.1", git = "https://github.com/AppFlowy-IO/AppFlowy-LocalAI", rev = "b803d8a8fd6b1587449e869b3a7a1ac687cf630b" } +appflowy-local-ai = { version = "0.1", git = "https://github.com/AppFlowy-IO/AppFlowy-LocalAI", rev = "346020270a0a3d3c82a60b545cd3f52144d56beb" } +appflowy-plugin = { version = "0.1", git = "https://github.com/AppFlowy-IO/AppFlowy-LocalAI", rev = "346020270a0a3d3c82a60b545cd3f52144d56beb" } diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.lock b/frontend/appflowy_web_app/src-tauri/Cargo.lock index 6f2f64dcde..1ff9399dcb 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.lock +++ b/frontend/appflowy_web_app/src-tauri/Cargo.lock @@ -197,7 +197,7 @@ dependencies = [ [[package]] name = "appflowy-local-ai" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-LocalAI?rev=b803d8a8fd6b1587449e869b3a7a1ac687cf630b#b803d8a8fd6b1587449e869b3a7a1ac687cf630b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-LocalAI?rev=346020270a0a3d3c82a60b545cd3f52144d56beb#346020270a0a3d3c82a60b545cd3f52144d56beb" dependencies = [ "anyhow", "appflowy-plugin", @@ -216,7 +216,7 @@ dependencies = [ [[package]] name = "appflowy-plugin" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-LocalAI?rev=b803d8a8fd6b1587449e869b3a7a1ac687cf630b#b803d8a8fd6b1587449e869b3a7a1ac687cf630b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-LocalAI?rev=346020270a0a3d3c82a60b545cd3f52144d56beb#346020270a0a3d3c82a60b545cd3f52144d56beb" dependencies = [ "anyhow", "cfg-if", diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.toml b/frontend/appflowy_web_app/src-tauri/Cargo.toml index e71778dcd4..891010b501 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.toml +++ b/frontend/appflowy_web_app/src-tauri/Cargo.toml @@ -128,6 +128,6 @@ collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy- # To update the commit ID, run: # scripts/tool/update_local_ai_rev.sh new_rev_id # ⚠️⚠️⚠️️ -appflowy-local-ai = { version = "0.1", git = "https://github.com/AppFlowy-IO/AppFlowy-LocalAI", rev = "b803d8a8fd6b1587449e869b3a7a1ac687cf630b" } -appflowy-plugin = { version = "0.1", git = "https://github.com/AppFlowy-IO/AppFlowy-LocalAI", rev = "b803d8a8fd6b1587449e869b3a7a1ac687cf630b" } +appflowy-local-ai = { version = "0.1", git = "https://github.com/AppFlowy-IO/AppFlowy-LocalAI", rev = "346020270a0a3d3c82a60b545cd3f52144d56beb" } +appflowy-plugin = { version = "0.1", git = "https://github.com/AppFlowy-IO/AppFlowy-LocalAI", rev = "346020270a0a3d3c82a60b545cd3f52144d56beb" } diff --git a/frontend/resources/translations/en.json b/frontend/resources/translations/en.json index bc68914b9b..9523d56620 100644 --- a/frontend/resources/translations/en.json +++ b/frontend/resources/translations/en.json @@ -632,6 +632,8 @@ "localAILoaded": "Local AI Model successfully added and ready to use", "localAILoading": "Local AI Model is loading...", "localAIStopped": "Local AI Model stopped", + "failToLoadLocalAI": "Failed to start local AI", + "restartLocalAI": "Restart Local AI", "title": "AI API Keys", "openAILabel": "OpenAI API key", "openAITooltip": "You can find your Secret API key on the API key page", diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index fb17ab7072..7209faff45 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -197,7 +197,7 @@ dependencies = [ [[package]] name = "appflowy-local-ai" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-LocalAI?rev=b803d8a8fd6b1587449e869b3a7a1ac687cf630b#b803d8a8fd6b1587449e869b3a7a1ac687cf630b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-LocalAI?rev=346020270a0a3d3c82a60b545cd3f52144d56beb#346020270a0a3d3c82a60b545cd3f52144d56beb" dependencies = [ "anyhow", "appflowy-plugin", @@ -216,7 +216,7 @@ dependencies = [ [[package]] name = "appflowy-plugin" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-LocalAI?rev=b803d8a8fd6b1587449e869b3a7a1ac687cf630b#b803d8a8fd6b1587449e869b3a7a1ac687cf630b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-LocalAI?rev=346020270a0a3d3c82a60b545cd3f52144d56beb#346020270a0a3d3c82a60b545cd3f52144d56beb" dependencies = [ "anyhow", "cfg-if", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index ad3c11761d..1331491442 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -151,5 +151,5 @@ collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy- # To update the commit ID, run: # scripts/tool/update_local_ai_rev.sh new_rev_id # ⚠️⚠️⚠️️ -appflowy-local-ai = { version = "0.1", git = "https://github.com/AppFlowy-IO/AppFlowy-LocalAI", rev = "b803d8a8fd6b1587449e869b3a7a1ac687cf630b" } -appflowy-plugin = { version = "0.1", git = "https://github.com/AppFlowy-IO/AppFlowy-LocalAI", rev = "b803d8a8fd6b1587449e869b3a7a1ac687cf630b" } +appflowy-local-ai = { version = "0.1", git = "https://github.com/AppFlowy-IO/AppFlowy-LocalAI", rev = "346020270a0a3d3c82a60b545cd3f52144d56beb" } +appflowy-plugin = { version = "0.1", git = "https://github.com/AppFlowy-IO/AppFlowy-LocalAI", rev = "346020270a0a3d3c82a60b545cd3f52144d56beb" } diff --git a/frontend/rust-lib/flowy-chat/src/event_handler.rs b/frontend/rust-lib/flowy-chat/src/event_handler.rs index fead2c476b..c16b4763e4 100644 --- a/frontend/rust-lib/flowy-chat/src/event_handler.rs +++ b/frontend/rust-lib/flowy-chat/src/event_handler.rs @@ -234,3 +234,12 @@ pub(crate) async fn get_plugin_state_handler( let state = chat_manager.local_ai_controller.get_plugin_state(); data_result_ok(state) } + +#[tracing::instrument(level = "debug", skip_all, err)] +pub(crate) async fn restart_local_ai_handler( + chat_manager: AFPluginState>, +) -> Result<(), FlowyError> { + let chat_manager = upgrade_chat_manager(chat_manager)?; + chat_manager.local_ai_controller.restart(); + Ok(()) +} diff --git a/frontend/rust-lib/flowy-chat/src/event_map.rs b/frontend/rust-lib/flowy-chat/src/event_map.rs index 72ac807b7d..ca930d5ad0 100644 --- a/frontend/rust-lib/flowy-chat/src/event_map.rs +++ b/frontend/rust-lib/flowy-chat/src/event_map.rs @@ -41,6 +41,7 @@ pub fn init(chat_manager: Weak) -> AFPlugin { cancel_download_llm_resource_handler, ) .event(ChatEvent::GetPluginState, get_plugin_state_handler) + .event(ChatEvent::RestartLocalAI, restart_local_ai_handler) } #[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)] @@ -91,4 +92,7 @@ pub enum ChatEvent { #[event(output = "PluginStatePB")] GetPluginState = 14, + + #[event()] + RestartLocalAI = 15, } diff --git a/frontend/rust-lib/flowy-chat/src/local_ai/local_llm_chat.rs b/frontend/rust-lib/flowy-chat/src/local_ai/local_llm_chat.rs index 0b0aa68d52..21db67e30e 100644 --- a/frontend/rust-lib/flowy-chat/src/local_ai/local_llm_chat.rs +++ b/frontend/rust-lib/flowy-chat/src/local_ai/local_llm_chat.rs @@ -59,8 +59,8 @@ impl LocalAIController { let mut rx = llm_chat.subscribe_running_state(); tokio::spawn(async move { while let Some(state) = rx.next().await { + info!("[AI Plugin] state: {:?}", state); let new_state = RunningStatePB::from(state); - info!("[AI Plugin] state: {:?}", new_state); send_notification( "appflowy_chat_plugin", ChatNotification::UpdateChatPluginState, @@ -84,7 +84,9 @@ impl LocalAIController { tokio::spawn(async move { while rx.recv().await.is_some() { if let Ok(chat_config) = cloned_llm_res.get_ai_plugin_config() { - initialize_chat_plugin(&cloned_llm_chat, chat_config).unwrap(); + if let Err(err) = initialize_chat_plugin(&cloned_llm_chat, chat_config) { + error!("[AI Plugin] failed to setup plugin: {:?}", err); + } } } }); @@ -184,6 +186,14 @@ impl LocalAIController { state: RunningStatePB::from(state), } } + + pub fn restart(&self) { + if let Ok(chat_config) = self.llm_res.get_ai_plugin_config() { + if let Err(err) = initialize_chat_plugin(&self.llm_chat, chat_config) { + error!("[AI Plugin] failed to setup plugin: {:?}", err); + } + } + } } fn initialize_chat_plugin(