chore: show plugin state (#5740)

* chore: show plugin state

* chore: flutter analyzer

* chore: update
This commit is contained in:
Nathan.fooo 2024-07-15 22:45:53 +08:00 committed by GitHub
parent ff23165d3e
commit c6ad57f11d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 251 additions and 55 deletions

View File

@ -15,7 +15,6 @@ extension AppFlowyAuthTest on WidgetTester {
Future<void> tapGoogleLoginInButton() async { Future<void> tapGoogleLoginInButton() async {
await tapButton( await tapButton(
find.byKey(const Key('signInWithGoogleButton')), find.byKey(const Key('signInWithGoogleButton')),
milliseconds: 3000,
); );
} }

View File

@ -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/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-chat/entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-chat/entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
@ -9,18 +10,53 @@ class ChatFileBloc extends Bloc<ChatFileEvent, ChatFileState> {
ChatFileBloc({ ChatFileBloc({
required String chatId, required String chatId,
dynamic message, dynamic message,
}) : super(ChatFileState.initial(message)) { }) : listener = LocalLLMListener(),
super(ChatFileState.initial(message)) {
listener.start(
stateCallback: (pluginState) {
if (!isClosed) {
add(ChatFileEvent.updateLocalAIState(pluginState));
}
},
);
on<ChatFileEvent>( on<ChatFileEvent>(
(event, emit) async { (event, emit) async {
await event.when( 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) { newFile: (String filePath) {
final payload = ChatFilePB(filePath: filePath, chatId: chatId); final payload = ChatFilePB(filePath: filePath, chatId: chatId);
ChatEventChatWithFile(payload).send(); ChatEventChatWithFile(payload).send();
}, },
updateLocalAIState: (PluginStatePB pluginState) {
emit(
state.copyWith(
supportChatWithFile:
pluginState.state == RunningStatePB.Running,
),
); );
}, },
); );
},
);
}
final LocalLLMListener listener;
@override
Future<void> close() async {
await listener.stop();
return super.close();
} }
} }
@ -28,12 +64,15 @@ class ChatFileBloc extends Bloc<ChatFileEvent, ChatFileState> {
class ChatFileEvent with _$ChatFileEvent { class ChatFileEvent with _$ChatFileEvent {
const factory ChatFileEvent.initial() = Initial; const factory ChatFileEvent.initial() = Initial;
const factory ChatFileEvent.newFile(String filePath) = _NewFile; const factory ChatFileEvent.newFile(String filePath) = _NewFile;
const factory ChatFileEvent.updateLocalAIState(PluginStatePB pluginState) =
_UpdateLocalAIState;
} }
@freezed @freezed
class ChatFileState with _$ChatFileState { class ChatFileState with _$ChatFileState {
const factory ChatFileState({ const factory ChatFileState({
required String text, required String text,
@Default(false) bool supportChatWithFile,
}) = _ChatFileState; }) = _ChatFileState;
factory ChatFileState.initial(dynamic text) { factory ChatFileState.initial(dynamic text) {

View File

@ -71,7 +71,8 @@ class AIChatPage extends StatelessWidget {
create: (context) => ChatFileBloc(chatId: view.id.toString()), create: (context) => ChatFileBloc(chatId: view.id.toString()),
child: BlocBuilder<ChatFileBloc, ChatFileState>( child: BlocBuilder<ChatFileBloc, ChatFileState>(
builder: (context, state) { builder: (context, state) {
return DropTarget( return state.supportChatWithFile
? DropTarget(
onDragDone: (DropDoneDetails detail) async { onDragDone: (DropDoneDetails detail) async {
for (final file in detail.files) { for (final file in detail.files) {
context context
@ -83,6 +84,10 @@ class AIChatPage extends StatelessWidget {
view: view, view: view,
userProfile: userProfile, userProfile: userProfile,
), ),
)
: _ChatContentPage(
view: view,
userProfile: userProfile,
); );
}, },
), ),

View File

@ -20,7 +20,7 @@ class LocalAISettingBloc
listener.start( listener.start(
stateCallback: (newState) { stateCallback: (newState) {
if (!isClosed) { if (!isClosed) {
add(LocalAISettingEvent.updateLLMRunningState(newState)); add(LocalAISettingEvent.updateLLMRunningState(newState.state));
} }
}, },
); );
@ -51,7 +51,11 @@ class LocalAISettingBloc
); );
}, },
(err) { (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)); add(LocalAISettingEvent.didLoadModelInfo(result));
} }
} }
@override
Future<void> close() async {
await listener.stop();
return super.close();
}
} }
@freezed @freezed

View File

@ -9,7 +9,7 @@ import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart';
import 'package:appflowy_backend/rust_stream.dart'; import 'package:appflowy_backend/rust_stream.dart';
import 'package:appflowy_result/appflowy_result.dart'; import 'package:appflowy_result/appflowy_result.dart';
typedef PluginStateCallback = void Function(RunningStatePB state); typedef PluginStateCallback = void Function(PluginStatePB state);
class LocalLLMListener { class LocalLLMListener {
LocalLLMListener() { LocalLLMListener() {
@ -39,7 +39,7 @@ class LocalLLMListener {
result.map((r) { result.map((r) {
switch (ty) { switch (ty) {
case ChatNotification.UpdateChatPluginState: case ChatNotification.UpdateChatPluginState:
stateCallback?.call(PluginStatePB.fromBuffer(r).state); stateCallback?.call(PluginStatePB.fromBuffer(r));
break; break;
default: default:
break; break;

View File

@ -1,24 +1,67 @@
import 'dart:async'; 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:appflowy_backend/protobuf/flowy-chat/entities.pb.dart';
import 'package:bloc/bloc.dart'; import 'package:bloc/bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
part 'plugin_state_bloc.freezed.dart'; part 'plugin_state_bloc.freezed.dart';
class PluginStateBloc extends Bloc<PluginStateEvent, PluginState> { class PluginStateBloc extends Bloc<PluginStateEvent, PluginStateState> {
PluginStateBloc() PluginStateBloc()
: super( : listener = LocalLLMListener(),
const PluginState(runningState: RunningStatePB.Connecting), super(const PluginStateState(action: PluginStateAction.init())) {
) { listener.start(
stateCallback: (pluginState) {
if (!isClosed) {
add(PluginStateEvent.updateState(pluginState));
}
},
);
on<PluginStateEvent>(_handleEvent); on<PluginStateEvent>(_handleEvent);
} }
final LocalLLMListener listener;
@override
Future<void> close() async {
await listener.stop();
return super.close();
}
Future<void> _handleEvent( Future<void> _handleEvent(
PluginStateEvent event, PluginStateEvent event,
Emitter<PluginState> emit, Emitter<PluginStateState> emit,
) async { ) async {
await event.when( 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<PluginStateEvent, PluginState> {
@freezed @freezed
class PluginStateEvent with _$PluginStateEvent { class PluginStateEvent with _$PluginStateEvent {
const factory PluginStateEvent.started() = _Started; const factory PluginStateEvent.started() = _Started;
const factory PluginStateEvent.updateState(PluginStatePB pluginState) =
_UpdatePluginState;
const factory PluginStateEvent.restartLocalAI() = _RestartLocalAI;
} }
@freezed @freezed
class PluginState with _$PluginState { class PluginStateState with _$PluginStateState {
const factory PluginState({ const factory PluginStateState({required PluginStateAction action}) =
required RunningStatePB runningState, _PluginStateState;
}) = _PluginState; }
@freezed
class PluginStateAction with _$PluginStateAction {
const factory PluginStateAction.init() = _Init;
const factory PluginStateAction.ready() = _Ready;
const factory PluginStateAction.reloadRequired() = _ReloadRequired;
} }

View File

@ -2,9 +2,10 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/workspace/application/settings/ai/plugin_state_bloc.dart'; import 'package:appflowy/workspace/application/settings/ai/plugin_state_bloc.dart';
import 'package:easy_localization/easy_localization.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/style_widget/text.dart';
import 'package:flowy_infra_ui/widget/spacing.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'; import 'package:flutter_bloc/flutter_bloc.dart';
class CheckPluginStateIndicator extends StatelessWidget { class CheckPluginStateIndicator extends StatelessWidget {
@ -12,7 +13,74 @@ class CheckPluginStateIndicator extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DecoratedBox( return BlocProvider(
create: (context) =>
PluginStateBloc()..add(const PluginStateEvent.started()),
child: BlocBuilder<PluginStateBloc, PluginStateState>(
builder: (context, state) {
return state.action.when(
init: () => const _InitPlugin(),
ready: () => const _ReadyToUse(),
reloadRequired: () => const _ReloadButton(),
);
},
),
);
}
}
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<PluginStateBloc>().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( decoration: const BoxDecoration(
color: Color(0xFFEDF7ED), color: Color(0xFFEDF7ED),
borderRadius: BorderRadius.all( borderRadius: BorderRadius.all(
@ -20,9 +88,7 @@ class CheckPluginStateIndicator extends StatelessWidget {
), ),
), ),
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4), padding: const EdgeInsets.symmetric(vertical: 6),
child: BlocProvider(
create: (context) => PluginStateBloc(),
child: Row( child: Row(
children: [ children: [
const HSpace(8), const HSpace(8),

View File

@ -206,7 +206,7 @@ dependencies = [
[[package]] [[package]]
name = "appflowy-local-ai" name = "appflowy-local-ai"
version = "0.1.0" 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 = [ dependencies = [
"anyhow", "anyhow",
"appflowy-plugin", "appflowy-plugin",
@ -225,7 +225,7 @@ dependencies = [
[[package]] [[package]]
name = "appflowy-plugin" name = "appflowy-plugin"
version = "0.1.0" 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 = [ dependencies = [
"anyhow", "anyhow",
"cfg-if", "cfg-if",

View File

@ -128,5 +128,5 @@ collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-
# To update the commit ID, run: # To update the commit ID, run:
# scripts/tool/update_local_ai_rev.sh new_rev_id # 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-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 = "b803d8a8fd6b1587449e869b3a7a1ac687cf630b" } appflowy-plugin = { version = "0.1", git = "https://github.com/AppFlowy-IO/AppFlowy-LocalAI", rev = "346020270a0a3d3c82a60b545cd3f52144d56beb" }

View File

@ -197,7 +197,7 @@ dependencies = [
[[package]] [[package]]
name = "appflowy-local-ai" name = "appflowy-local-ai"
version = "0.1.0" 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 = [ dependencies = [
"anyhow", "anyhow",
"appflowy-plugin", "appflowy-plugin",
@ -216,7 +216,7 @@ dependencies = [
[[package]] [[package]]
name = "appflowy-plugin" name = "appflowy-plugin"
version = "0.1.0" 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 = [ dependencies = [
"anyhow", "anyhow",
"cfg-if", "cfg-if",

View File

@ -128,6 +128,6 @@ collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-
# To update the commit ID, run: # To update the commit ID, run:
# scripts/tool/update_local_ai_rev.sh new_rev_id # 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-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 = "b803d8a8fd6b1587449e869b3a7a1ac687cf630b" } appflowy-plugin = { version = "0.1", git = "https://github.com/AppFlowy-IO/AppFlowy-LocalAI", rev = "346020270a0a3d3c82a60b545cd3f52144d56beb" }

View File

@ -632,6 +632,8 @@
"localAILoaded": "Local AI Model successfully added and ready to use", "localAILoaded": "Local AI Model successfully added and ready to use",
"localAILoading": "Local AI Model is loading...", "localAILoading": "Local AI Model is loading...",
"localAIStopped": "Local AI Model stopped", "localAIStopped": "Local AI Model stopped",
"failToLoadLocalAI": "Failed to start local AI",
"restartLocalAI": "Restart Local AI",
"title": "AI API Keys", "title": "AI API Keys",
"openAILabel": "OpenAI API key", "openAILabel": "OpenAI API key",
"openAITooltip": "You can find your Secret API key on the API key page", "openAITooltip": "You can find your Secret API key on the API key page",

View File

@ -197,7 +197,7 @@ dependencies = [
[[package]] [[package]]
name = "appflowy-local-ai" name = "appflowy-local-ai"
version = "0.1.0" 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 = [ dependencies = [
"anyhow", "anyhow",
"appflowy-plugin", "appflowy-plugin",
@ -216,7 +216,7 @@ dependencies = [
[[package]] [[package]]
name = "appflowy-plugin" name = "appflowy-plugin"
version = "0.1.0" 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 = [ dependencies = [
"anyhow", "anyhow",
"cfg-if", "cfg-if",

View File

@ -151,5 +151,5 @@ collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-
# To update the commit ID, run: # To update the commit ID, run:
# scripts/tool/update_local_ai_rev.sh new_rev_id # 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-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 = "b803d8a8fd6b1587449e869b3a7a1ac687cf630b" } appflowy-plugin = { version = "0.1", git = "https://github.com/AppFlowy-IO/AppFlowy-LocalAI", rev = "346020270a0a3d3c82a60b545cd3f52144d56beb" }

View File

@ -234,3 +234,12 @@ pub(crate) async fn get_plugin_state_handler(
let state = chat_manager.local_ai_controller.get_plugin_state(); let state = chat_manager.local_ai_controller.get_plugin_state();
data_result_ok(state) data_result_ok(state)
} }
#[tracing::instrument(level = "debug", skip_all, err)]
pub(crate) async fn restart_local_ai_handler(
chat_manager: AFPluginState<Weak<ChatManager>>,
) -> Result<(), FlowyError> {
let chat_manager = upgrade_chat_manager(chat_manager)?;
chat_manager.local_ai_controller.restart();
Ok(())
}

View File

@ -41,6 +41,7 @@ pub fn init(chat_manager: Weak<ChatManager>) -> AFPlugin {
cancel_download_llm_resource_handler, cancel_download_llm_resource_handler,
) )
.event(ChatEvent::GetPluginState, get_plugin_state_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)] #[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
@ -91,4 +92,7 @@ pub enum ChatEvent {
#[event(output = "PluginStatePB")] #[event(output = "PluginStatePB")]
GetPluginState = 14, GetPluginState = 14,
#[event()]
RestartLocalAI = 15,
} }

View File

@ -59,8 +59,8 @@ impl LocalAIController {
let mut rx = llm_chat.subscribe_running_state(); let mut rx = llm_chat.subscribe_running_state();
tokio::spawn(async move { tokio::spawn(async move {
while let Some(state) = rx.next().await { while let Some(state) = rx.next().await {
info!("[AI Plugin] state: {:?}", state);
let new_state = RunningStatePB::from(state); let new_state = RunningStatePB::from(state);
info!("[AI Plugin] state: {:?}", new_state);
send_notification( send_notification(
"appflowy_chat_plugin", "appflowy_chat_plugin",
ChatNotification::UpdateChatPluginState, ChatNotification::UpdateChatPluginState,
@ -84,7 +84,9 @@ impl LocalAIController {
tokio::spawn(async move { tokio::spawn(async move {
while rx.recv().await.is_some() { while rx.recv().await.is_some() {
if let Ok(chat_config) = cloned_llm_res.get_ai_plugin_config() { 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), 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( fn initialize_chat_plugin(