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 703093a5eb..032ae0b5e5 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 @@ -7,6 +7,8 @@ import 'package:appflowy_backend/protobuf/flowy-ai/entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; +import 'chat_input_bloc.dart'; + part 'chat_file_bloc.freezed.dart'; class ChatFileBloc extends Bloc { @@ -46,9 +48,17 @@ class ChatFileBloc extends Bloc { ); }, newFile: (String filePath, String fileName) async { + final files = List.from(state.uploadFiles); + files.add(ChatFile(filePath: filePath, fileName: fileName)); emit( state.copyWith( - indexFileIndicator: IndexFileIndicator.indexing(fileName), + uploadFiles: files, + ), + ); + + emit( + state.copyWith( + uploadFileIndicator: UploadFileIndicator.uploading(fileName), ), ); final payload = ChatFilePB(filePath: filePath, chatId: chatId); @@ -57,14 +67,14 @@ class ChatFileBloc extends Bloc { if (!isClosed) { result.fold((_) { add( - ChatFileEvent.updateIndexFile( - IndexFileIndicator.finish(fileName), + ChatFileEvent.updateUploadState( + UploadFileIndicator.finish(fileName), ), ); }, (err) { add( - ChatFileEvent.updateIndexFile( - IndexFileIndicator.error(err.msg), + ChatFileEvent.updateUploadState( + UploadFileIndicator.error(err.msg), ), ); }); @@ -83,16 +93,31 @@ class ChatFileBloc extends Bloc { ), ); }, - updateIndexFile: (IndexFileIndicator indicator) { - emit( - state.copyWith(indexFileIndicator: indicator), - ); - }, updatePluginState: (LocalAIPluginStatePB chatState) { final fileEnabled = state.chatState?.fileEnabled ?? false; final supportChatWithFile = fileEnabled && chatState.state == RunningStatePB.Running; - emit(state.copyWith(supportChatWithFile: supportChatWithFile)); + + final aiType = chatState.state == RunningStatePB.Running + ? const AIType.localAI() + : const AIType.appflowyAI(); + + emit( + state.copyWith( + supportChatWithFile: supportChatWithFile, + aiType: aiType, + ), + ); + }, + clear: () { + emit( + state.copyWith( + uploadFiles: [], + ), + ); + }, + updateUploadState: (UploadFileIndicator indicator) { + emit(state.copyWith(uploadFileIndicator: indicator)); }, ); }, @@ -113,27 +138,40 @@ class ChatFileEvent with _$ChatFileEvent { const factory ChatFileEvent.initial() = Initial; const factory ChatFileEvent.newFile(String filePath, String fileName) = _NewFile; + const factory ChatFileEvent.clear() = _ClearFile; + const factory ChatFileEvent.updateUploadState(UploadFileIndicator indicator) = + _UpdateUploadState; const factory ChatFileEvent.updateChatState(LocalAIChatPB chatState) = _UpdateChatState; const factory ChatFileEvent.updatePluginState( LocalAIPluginStatePB chatState, ) = _UpdatePluginState; - const factory ChatFileEvent.updateIndexFile(IndexFileIndicator indicator) = - _UpdateIndexFile; } @freezed class ChatFileState with _$ChatFileState { const factory ChatFileState({ @Default(false) bool supportChatWithFile, - IndexFileIndicator? indexFileIndicator, + UploadFileIndicator? uploadFileIndicator, LocalAIChatPB? chatState, + @Default([]) List uploadFiles, + @Default(AIType.appflowyAI()) AIType aiType, }) = _ChatFileState; } @freezed -class IndexFileIndicator with _$IndexFileIndicator { - const factory IndexFileIndicator.finish(String fileName) = _Finish; - const factory IndexFileIndicator.indexing(String fileName) = _Indexing; - const factory IndexFileIndicator.error(String error) = _Error; +class UploadFileIndicator with _$UploadFileIndicator { + const factory UploadFileIndicator.finish(String fileName) = _Finish; + const factory UploadFileIndicator.uploading(String fileName) = _Uploading; + const factory UploadFileIndicator.error(String error) = _Error; +} + +class ChatFile { + ChatFile({ + required this.filePath, + required this.fileName, + }); + + final String filePath; + final String fileName; } diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_service.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_service.dart index dc2bc5dbbc..6c627e56c5 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_service.dart @@ -23,7 +23,7 @@ Future> metadataPBFromMetadata( ChatMessageMetaPB( id: view.id, name: view.name, - text: pb.text, + data: pb.text, source: "appflowy document", ), ); 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 d33b6ac8cb..2fb0869886 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -4,10 +4,10 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/ai_chat/application/chat_bloc.dart'; import 'package:appflowy/plugins/ai_chat/application/chat_file_bloc.dart'; import 'package:appflowy/plugins/ai_chat/application/chat_input_bloc.dart'; -import 'package:appflowy/plugins/ai_chat/presentation/ai_message_bubble.dart'; import 'package:appflowy/plugins/ai_chat/presentation/chat_related_question.dart'; -import 'package:appflowy/plugins/ai_chat/presentation/other_user_message_bubble.dart'; -import 'package:appflowy/plugins/ai_chat/presentation/user_message_bubble.dart'; +import 'package:appflowy/plugins/ai_chat/presentation/message/ai_message_bubble.dart'; +import 'package:appflowy/plugins/ai_chat/presentation/message/other_user_message_bubble.dart'; +import 'package:appflowy/plugins/ai_chat/presentation/message/user_message_bubble.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/space/shared_widget.dart'; import 'package:appflowy/workspace/presentation/home/toast.dart'; import 'package:appflowy/workspace/presentation/widgets/dialogs.dart'; @@ -79,7 +79,6 @@ class AIChatPage extends StatelessWidget { return MultiBlocProvider( providers: [ /// [ChatBloc] is used to handle chat messages including send/receive message - /// BlocProvider( create: (_) => ChatBloc( view: view, @@ -88,14 +87,12 @@ class AIChatPage extends StatelessWidget { ), /// [ChatFileBloc] is used to handle file indexing as a chat context - /// BlocProvider( - create: (_) => ChatFileBloc(chatId: view.id.toString()) + create: (_) => ChatFileBloc(chatId: view.id) ..add(const ChatFileEvent.initial()), ), /// [ChatInputStateBloc] is used to handle chat input text field state - /// BlocProvider( create: (_) => ChatInputStateBloc()..add(const ChatInputStateEvent.started()), @@ -105,9 +102,9 @@ class AIChatPage extends StatelessWidget { ], child: BlocListener( listenWhen: (previous, current) => - previous.indexFileIndicator != current.indexFileIndicator, + previous.uploadFileIndicator != current.uploadFileIndicator, listener: (context, state) { - _handleIndexIndicator(state.indexFileIndicator, context); + _handleIndexIndicator(state.uploadFileIndicator, context); }, child: BlocBuilder( builder: (context, state) { @@ -150,7 +147,7 @@ class AIChatPage extends StatelessWidget { } void _handleIndexIndicator( - IndexFileIndicator? indicator, + UploadFileIndicator? indicator, BuildContext context, ) { if (indicator != null) { @@ -161,7 +158,7 @@ class AIChatPage extends StatelessWidget { LocaleKeys.chat_indexFileSuccess.tr(args: [fileName]), ); }, - indexing: (fileName) { + uploading: (fileName) { showSnackBarMessage( context, LocaleKeys.chat_indexingFile.tr(args: [fileName]), @@ -305,7 +302,7 @@ class _ChatContentPageState extends State<_ChatContentPage> { // We use custom bottom widget for chat input, so // do not need to handle this event. }, - customBottomWidget: buildChatInput(blocContext), + customBottomWidget: buildBottom(blocContext), user: _user, theme: buildTheme(context), onEndReached: () async { @@ -488,7 +485,7 @@ class _ChatContentPageState extends State<_ChatContentPage> { } } - Widget buildChatInput(BuildContext context) { + Widget buildBottom(BuildContext context) { return ClipRect( child: Padding( padding: AIChatUILayout.safeAreaInsets(context), diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_avatar.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_avatar.dart index b91d4e1099..c9f1422900 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_avatar.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_avatar.dart @@ -8,6 +8,8 @@ import 'package:flowy_infra/size.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:string_validator/string_validator.dart'; +const defaultAvatarSize = 30.0; + class ChatChatUserAvatar extends StatelessWidget { const ChatChatUserAvatar({required this.userId, super.key}); @@ -33,15 +35,18 @@ class ChatBorderedCircleAvatar extends StatelessWidget { @override Widget build(BuildContext context) { - return CircleAvatar( - backgroundColor: border.color, - child: ConstrainedBox( - constraints: const BoxConstraints.expand(), - child: CircleAvatar( - backgroundImage: backgroundImage, - backgroundColor: - Theme.of(context).colorScheme.surfaceContainerHighest, - child: child, + return SizedBox( + width: defaultAvatarSize, + child: CircleAvatar( + backgroundColor: border.color, + child: ConstrainedBox( + constraints: const BoxConstraints.expand(), + child: CircleAvatar( + backgroundImage: backgroundImage, + backgroundColor: + Theme.of(context).colorScheme.surfaceContainerHighest, + child: child, + ), ), ), ); @@ -53,7 +58,7 @@ class ChatUserAvatar extends StatelessWidget { super.key, required this.iconUrl, required this.name, - required this.size, + this.size = defaultAvatarSize, this.isHovering = false, this.defaultName, }); diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input/chat_attachment.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input/chat_attachment.dart new file mode 100644 index 0000000000..13cbbadfb1 --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input/chat_attachment.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:appflowy/generated/flowy_svgs.g.dart'; +import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flowy_infra/theme_extension.dart'; +import 'package:flowy_infra_ui/style_widget/icon_button.dart'; +import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; + +class ChatInputAttachment extends StatelessWidget { + const ChatInputAttachment({required this.onTap, super.key}); + + final VoidCallback onTap; + + @override + Widget build(BuildContext context) { + return FlowyTooltip( + message: LocaleKeys.chat_uploadFile.tr(), + child: FlowyIconButton( + hoverColor: AFThemeExtension.of(context).lightGreyHover, + radius: BorderRadius.circular(18), + icon: FlowySvg( + FlowySvgs.ai_attachment_s, + size: const Size.square(20), + color: Theme.of(context).colorScheme.primary, + ), + onPressed: onTap, + ), + ); + } +} diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input/chat_input.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input/chat_input.dart index 92b911c406..86eedc786c 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input/chat_input.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input/chat_input.dart @@ -1,28 +1,31 @@ +import 'package:appflowy/plugins/ai_chat/application/chat_file_bloc.dart'; import 'package:appflowy/plugins/ai_chat/application/chat_input_action_bloc.dart'; -import 'package:appflowy/plugins/ai_chat/application/chat_input_action_control.dart'; import 'package:appflowy/plugins/ai_chat/application/chat_input_bloc.dart'; import 'package:appflowy/plugins/ai_chat/presentation/chat_input_action_menu.dart'; +import 'package:appflowy/plugins/ai_chat/application/chat_input_action_control.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mobile_page_selector_sheet.dart'; +import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/workspace/application/view/view_ext.dart'; import 'package:extended_text_field/extended_text_field.dart'; +import 'package:flowy_infra/file_picker/file_picker_service.dart'; import 'package:flowy_infra/platform_extension.dart'; import 'package:flowy_infra/theme_extension.dart'; -import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_chat_types/flutter_chat_types.dart' as types; import 'package:flutter_chat_ui/flutter_chat_ui.dart'; import 'chat_at_button.dart'; -import 'chat_input_span.dart'; +import 'chat_attachment.dart'; import 'chat_send_button.dart'; +import 'chat_input_span.dart'; class ChatInput extends StatefulWidget { /// Creates [ChatInput] widget. const ChatInput({ super.key, - this.isAttachmentUploading, this.onAttachmentPressed, required this.onSendPressed, required this.chatId, @@ -33,7 +36,6 @@ class ChatInput extends StatefulWidget { required this.aiType, }); - final bool? isAttachmentUploading; final VoidCallback? onAttachmentPressed; final void Function(types.PartialText) onSendPressed; final void Function() onStopStreaming; @@ -81,11 +83,16 @@ class _ChatInputState extends State { }, ); + _inputFocusNode.addListener(() { + setState(() {}); + }); + _inputActionControl = ChatInputActionControl( chatId: widget.chatId, textController: _textController, textFieldFocusNode: _inputFocusNode, ); + _inputFocusNode.requestFocus(); _handleSendButtonVisibilityModeChange(); } @@ -101,7 +108,6 @@ class _ChatInputState extends State { Widget build(BuildContext context) { const buttonPadding = EdgeInsets.symmetric(horizontal: 2); const inputPadding = EdgeInsets.all(6); - final textPadding = isMobile ? const EdgeInsets.only(left: 8.0, right: 4.0) : const EdgeInsets.symmetric(horizontal: 16); @@ -109,32 +115,38 @@ class _ChatInputState extends State { final color = isMobile ? Colors.transparent : Theme.of(context).colorScheme.surfaceContainerHighest; - final elevation = isMobile ? 0.0 : 0.6; - final space = isMobile ? 8.0 : 14.0; - return Focus( - child: Padding( - padding: inputPadding, + return Padding( + padding: inputPadding, + // ignore: use_decorated_box + child: Container( + decoration: BoxDecoration( + border: Border.all( + color: _inputFocusNode.hasFocus + ? Theme.of(context).colorScheme.primary.withOpacity(0.6) + : Colors.transparent, + ), + borderRadius: borderRadius, + ), child: Material( borderRadius: borderRadius, color: color, - elevation: elevation, - child: Row( - children: [ - if (widget.onAttachmentPressed != null) - AttachmentButton( - isLoading: widget.isAttachmentUploading ?? false, - onPressed: widget.onAttachmentPressed, - padding: buttonPadding, - ), - Expanded( - child: _inputTextField(context, textPadding), - ), - if (widget.aiType == const AIType.appflowyAI()) - _atButton(buttonPadding), - _sendButton(buttonPadding), - HSpace(space), - ], + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Row( + children: [ + // TODO(lucas): support mobile + if (PlatformExtension.isDesktop && + widget.aiType == const AIType.localAI()) + _attachmentButton(buttonPadding), + Expanded(child: _inputTextField(context, textPadding)), + + if (PlatformExtension.isDesktop && + widget.aiType == const AIType.appflowyAI()) + _atButton(buttonPadding), + _sendButton(buttonPadding), + ], + ), ), ), ), @@ -282,20 +294,54 @@ class _ChatInputState extends State { Widget _sendButton(EdgeInsets buttonPadding) { return Padding( padding: buttonPadding, - child: ChatInputSendButton( - onSendPressed: () { - if (!_sendButtonEnabled) { - return; - } + child: SizedBox.square( + dimension: 26, + child: ChatInputSendButton( + onSendPressed: () { + if (!_sendButtonEnabled) { + return; + } - if (!widget.isStreaming) { - widget.onStopStreaming(); - _handleSendPressed(); - } - }, - onStopStreaming: () => widget.onStopStreaming(), - isStreaming: widget.isStreaming, - enabled: _sendButtonEnabled, + if (!widget.isStreaming) { + widget.onStopStreaming(); + _handleSendPressed(); + } + }, + onStopStreaming: () => widget.onStopStreaming(), + isStreaming: widget.isStreaming, + enabled: _sendButtonEnabled, + ), + ), + ); + } + + Widget _attachmentButton(EdgeInsets buttonPadding) { + return Padding( + padding: buttonPadding, + child: SizedBox.square( + dimension: 26, + child: ChatInputAttachment( + onTap: () async { + final path = await getIt().pickFiles( + dialogTitle: '', + type: FileType.custom, + allowedExtensions: ["pdf"], + ); + if (path == null) { + return; + } + + for (final file in path.files) { + if (file.path != null) { + if (mounted) { + context + .read() + .add(ChatFileEvent.newFile(file.path!, file.name)); + } + } + } + }, + ), ), ); } @@ -303,14 +349,17 @@ class _ChatInputState extends State { Widget _atButton(EdgeInsets buttonPadding) { return Padding( padding: buttonPadding, - child: ChatInputAtButton( - onTap: () { - _textController.text += '@'; - if (!isMobile) { - _inputFocusNode.requestFocus(); - } - _handleOnTextChange(context, _textController.text); - }, + child: SizedBox.square( + dimension: 26, + child: ChatInputAtButton( + onTap: () { + _textController.text += '@'; + if (!isMobile) { + _inputFocusNode.requestFocus(); + } + _handleOnTextChange(context, _textController.text); + }, + ), ), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input/chat_send_button.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input/chat_send_button.dart index d3c7a11606..33c9e47b02 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input/chat_send_button.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input/chat_send_button.dart @@ -38,7 +38,7 @@ class ChatInputSendButton extends StatelessWidget { radius: BorderRadius.circular(18), icon: FlowySvg( FlowySvgs.send_s, - size: const Size.square(20), + size: const Size.square(14), color: enabled ? Theme.of(context).colorScheme.primary : null, ), onPressed: onSendPressed, diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/ai_message_bubble.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/message/ai_message_bubble.dart similarity index 96% rename from frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/ai_message_bubble.dart rename to frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/message/ai_message_bubble.dart index 5ce43f8182..3e29af1a62 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/ai_message_bubble.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/message/ai_message_bubble.dart @@ -49,8 +49,9 @@ class ChatAIMessageBubble extends StatelessWidget { children: [ const ChatBorderedCircleAvatar( child: FlowySvg( - FlowySvgs.flowy_ai_chat_logo_s, - size: Size.square(24), + FlowySvgs.flowy_logo_s, + size: Size.square(20), + blendMode: null, ), ), Expanded(child: widget), @@ -177,10 +178,9 @@ class CopyButton extends StatelessWidget { width: 24, hoverColor: AFThemeExtension.of(context).lightGreyHover, fillColor: Theme.of(context).cardColor, - icon: FlowySvg( - FlowySvgs.ai_copy_s, - size: const Size.square(14), - color: Theme.of(context).colorScheme.primary, + icon: const FlowySvg( + FlowySvgs.copy_s, + size: Size.square(20), ), onPressed: () async { final document = customMarkdownToDocument(textMessage.text); diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/message/ai_metadata.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/message/ai_metadata.dart index 3b3f06114b..f807d84c96 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/message/ai_metadata.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/message/ai_metadata.dart @@ -51,9 +51,7 @@ class AIMessageMetadata extends StatelessWidget { fontSize: 14, ), ), - onTap: () { - onSelectedMetadata(m); - }, + onTap: () => onSelectedMetadata(m), ), ), ) diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/other_user_message_bubble.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/message/other_user_message_bubble.dart similarity index 99% rename from frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/other_user_message_bubble.dart rename to frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/message/other_user_message_bubble.dart index 676df936c1..899c0bec3c 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/other_user_message_bubble.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/message/other_user_message_bubble.dart @@ -64,7 +64,6 @@ class OtherUserMessageBubble extends StatelessWidget { return ChatUserAvatar( iconUrl: member?.info.avatarUrl ?? "", name: member?.info.name ?? "", - size: 36, defaultName: "", ); }, diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/user_message_bubble.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/message/user_message_bubble.dart similarity index 99% rename from frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/user_message_bubble.dart rename to frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/message/user_message_bubble.dart index 9374af8a7b..e0cdc45562 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/user_message_bubble.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/message/user_message_bubble.dart @@ -68,7 +68,6 @@ class ChatUserMessageBubble extends StatelessWidget { child: ChatUserAvatar( iconUrl: member?.info.avatarUrl ?? "", name: member?.info.name ?? "", - size: 36, ), ), ], diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index e81c737826..2f5b138d61 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -172,7 +172,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "bincode", @@ -192,7 +192,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "bytes", @@ -423,7 +423,7 @@ dependencies = [ "bitflags 2.4.0", "cexpr", "clang-sys", - "itertools 0.12.1", + "itertools 0.10.5", "lazy_static", "lazycell", "proc-macro2", @@ -826,7 +826,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "again", "anyhow", @@ -876,7 +876,7 @@ dependencies = [ [[package]] name = "client-api-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "collab-entity", "collab-rt-entity", @@ -888,7 +888,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "futures-channel", "futures-util", @@ -1132,7 +1132,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "bincode", @@ -1157,7 +1157,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "async-trait", @@ -1532,7 +1532,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "app-error", @@ -3051,7 +3051,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "futures-util", @@ -3068,7 +3068,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "app-error", @@ -3500,7 +3500,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "bytes", @@ -6098,7 +6098,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index cdfd51ef4f..103ea91b32 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -53,7 +53,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "40bd6b784eced6fe43c95941420b3ce444b0a60c" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "30c7acce96f1a7b8865c05e70b6e525eaa286b37" } [dependencies] serde_json.workspace = true diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.lock b/frontend/appflowy_web_app/src-tauri/Cargo.lock index 2af380a87a..9f8bf03b05 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.lock +++ b/frontend/appflowy_web_app/src-tauri/Cargo.lock @@ -163,7 +163,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "bincode", @@ -183,7 +183,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "bytes", @@ -800,7 +800,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "again", "anyhow", @@ -850,7 +850,7 @@ dependencies = [ [[package]] name = "client-api-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "collab-entity", "collab-rt-entity", @@ -862,7 +862,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "futures-channel", "futures-util", @@ -1115,7 +1115,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "bincode", @@ -1140,7 +1140,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "async-trait", @@ -1411,7 +1411,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.10", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1522,7 +1522,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "app-error", @@ -3118,7 +3118,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "futures-util", @@ -3135,7 +3135,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "app-error", @@ -3572,7 +3572,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "bytes", @@ -6162,7 +6162,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.toml b/frontend/appflowy_web_app/src-tauri/Cargo.toml index 20a052adb0..7815cbbe03 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.toml +++ b/frontend/appflowy_web_app/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "40bd6b784eced6fe43c95941420b3ce444b0a60c" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "30c7acce96f1a7b8865c05e70b6e525eaa286b37" } [dependencies] serde_json.workspace = true diff --git a/frontend/resources/flowy_icons/16x/ai_attachment.svg b/frontend/resources/flowy_icons/16x/ai_attachment.svg new file mode 100644 index 0000000000..60a3cd5177 --- /dev/null +++ b/frontend/resources/flowy_icons/16x/ai_attachment.svg @@ -0,0 +1 @@ +Paperclip 1 Streamline Icon: https://streamlinehq.com \ No newline at end of file diff --git a/frontend/resources/flowy_icons/16x/flowy_logo.svg b/frontend/resources/flowy_icons/16x/flowy_logo.svg new file mode 100644 index 0000000000..96af87f8ff --- /dev/null +++ b/frontend/resources/flowy_icons/16x/flowy_logo.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/frontend/resources/flowy_icons/16x/send.svg b/frontend/resources/flowy_icons/16x/send.svg index a5f933a8ca..b141b255b0 100644 --- a/frontend/resources/flowy_icons/16x/send.svg +++ b/frontend/resources/flowy_icons/16x/send.svg @@ -1,3 +1 @@ - - - +Arrow Up Streamline Icon: https://streamlinehq.com \ No newline at end of file diff --git a/frontend/resources/translations/en.json b/frontend/resources/translations/en.json index 49a40c640d..c39d31392e 100644 --- a/frontend/resources/translations/en.json +++ b/frontend/resources/translations/en.json @@ -177,6 +177,7 @@ "referenceSource": "{} source found", "referenceSources": "{} sources found", "clickToMention": "Click to mention a page", + "uploadFile": "Upload PDFs, md or txt files to chat with", "indexingFile": "Indexing {}" }, "trash": { @@ -2377,4 +2378,4 @@ "commentAddedSuccessfully": "Comment added successfully.", "commentAddedSuccessTip": "You've just added or replied to a comment. Would you like to jump to the top to see the latest comments?" } -} +} \ No newline at end of file diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index adf338ec7b..9d993c5e22 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -163,7 +163,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "bincode", @@ -183,7 +183,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "bytes", @@ -718,7 +718,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "again", "anyhow", @@ -768,7 +768,7 @@ dependencies = [ [[package]] name = "client-api-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "collab-entity", "collab-rt-entity", @@ -780,7 +780,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "futures-channel", "futures-util", @@ -993,7 +993,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "bincode", @@ -1018,7 +1018,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "async-trait", @@ -1256,7 +1256,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1356,7 +1356,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "app-error", @@ -2730,7 +2730,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "futures-util", @@ -2747,7 +2747,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "app-error", @@ -3112,7 +3112,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "bytes", @@ -4068,7 +4068,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros", + "phf_macros 0.8.0", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -4088,6 +4088,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ + "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -4155,6 +4156,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.47", +] + [[package]] name = "phf_shared" version = "0.8.0" @@ -5307,7 +5321,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=40bd6b784eced6fe43c95941420b3ce444b0a60c#40bd6b784eced6fe43c95941420b3ce444b0a60c" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=30c7acce96f1a7b8865c05e70b6e525eaa286b37#30c7acce96f1a7b8865c05e70b6e525eaa286b37" dependencies = [ "anyhow", "app-error", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index ac2666ddc4..8fd538c6fb 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -99,8 +99,8 @@ zip = "2.1.3" # Run the script.add_workspace_members: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "40bd6b784eced6fe43c95941420b3ce444b0a60c" } -client-api-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "40bd6b784eced6fe43c95941420b3ce444b0a60c" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "30c7acce96f1a7b8865c05e70b6e525eaa286b37" } +client-api-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "30c7acce96f1a7b8865c05e70b6e525eaa286b37" } [profile.dev] opt-level = 0 diff --git a/frontend/rust-lib/flowy-ai-pub/src/cloud.rs b/frontend/rust-lib/flowy-ai-pub/src/cloud.rs index 8d7932dc01..2793cd18a6 100644 --- a/frontend/rust-lib/flowy-ai-pub/src/cloud.rs +++ b/frontend/rust-lib/flowy-ai-pub/src/cloud.rs @@ -12,7 +12,7 @@ use flowy_error::FlowyError; use futures::stream::BoxStream; use lib_infra::async_trait::async_trait; use lib_infra::future::FutureResult; -use std::path::PathBuf; +use std::path::Path; pub type ChatMessageStream = BoxStream<'static, Result>; pub type StreamAnswer = BoxStream<'static, Result>; @@ -83,7 +83,7 @@ pub trait ChatCloudService: Send + Sync + 'static { async fn index_file( &self, workspace_id: &str, - file_path: PathBuf, + file_path: &Path, chat_id: &str, ) -> Result<(), FlowyError>; diff --git a/frontend/rust-lib/flowy-ai/src/ai_manager.rs b/frontend/rust-lib/flowy-ai/src/ai_manager.rs index c0ae334f9f..424b141e4d 100644 --- a/frontend/rust-lib/flowy-ai/src/ai_manager.rs +++ b/frontend/rust-lib/flowy-ai/src/ai_manager.rs @@ -1,22 +1,19 @@ use crate::chat::Chat; use crate::entities::{ - ChatMessageListPB, ChatMessagePB, CreateChatContextPB, RepeatedRelatedQuestionPB, + ChatInfoPB, ChatMessageListPB, ChatMessagePB, FilePB, RepeatedRelatedQuestionPB, }; use crate::local_ai::local_llm_chat::LocalAIController; use crate::middleware::chat_service_mw::AICloudServiceMiddleware; -use crate::persistence::{insert_chat, ChatTable}; +use crate::persistence::{insert_chat, read_chat_metadata, ChatTable}; use appflowy_plugin::manager::PluginManager; use dashmap::DashMap; -use flowy_ai_pub::cloud::{ - ChatCloudService, ChatMessageMetadata, ChatMessageType, CreateTextChatContext, -}; +use flowy_ai_pub::cloud::{ChatCloudService, ChatMessageMetadata, ChatMessageType}; use flowy_error::{FlowyError, FlowyResult}; use flowy_sqlite::kv::KVStorePreferences; use flowy_sqlite::DBConnection; use lib_infra::util::timestamp; -use serde_json::json; use std::path::PathBuf; use std::sync::Arc; use tracing::{info, trace}; @@ -106,25 +103,22 @@ impl AIManager { Ok(()) } - pub async fn create_chat_context(&self, context: CreateChatContextPB) -> FlowyResult<()> { - let workspace_id = self.user_service.workspace_id()?; - let context = CreateTextChatContext { - chat_id: context.chat_id, - content_type: context.content_type, - text: context.text, - chunk_size: 2000, - chunk_overlap: 20, - metadata: context - .metadata - .into_iter() - .map(|(k, v)| (k, json!(v))) - .collect(), - }; - self - .cloud_service_wm - .create_chat_context(&workspace_id, context) - .await?; - Ok(()) + pub async fn get_chat_info(&self, chat_id: &str) -> FlowyResult { + let mut conn = self.user_service.sqlite_connection(0)?; + let metadata = read_chat_metadata(&mut conn, chat_id)?; + let files = metadata + .files + .into_iter() + .map(|file| FilePB { + id: file.id, + name: file.name, + }) + .collect(); + + Ok(ChatInfoPB { + chat_id: chat_id.to_string(), + files, + }) } pub async fn create_chat(&self, uid: &i64, chat_id: &str) -> Result, FlowyError> { @@ -260,10 +254,10 @@ fn save_chat(conn: DBConnection, chat_id: &str) -> FlowyResult<()> { chat_id: chat_id.to_string(), created_at: timestamp(), name: "".to_string(), - local_model_path: "".to_string(), - local_model_name: "".to_string(), + local_files: "".to_string(), + metadata: "".to_string(), local_enabled: false, - sync_to_cloud: true, + sync_to_cloud: false, }; insert_chat(conn, &row)?; diff --git a/frontend/rust-lib/flowy-ai/src/chat.rs b/frontend/rust-lib/flowy-ai/src/chat.rs index e3b0808afd..11116f451f 100644 --- a/frontend/rust-lib/flowy-ai/src/chat.rs +++ b/frontend/rust-lib/flowy-ai/src/chat.rs @@ -4,7 +4,10 @@ use crate::entities::{ }; use crate::middleware::chat_service_mw::AICloudServiceMiddleware; use crate::notification::{make_notification, ChatNotification}; -use crate::persistence::{insert_chat_messages, select_chat_messages, ChatMessageTable}; +use crate::persistence::{ + insert_chat_messages, read_chat_metadata, select_chat_messages, update_chat, ChatMessageTable, + ChatTableChangeset, +}; use allo_isolate::Isolate; use flowy_ai_pub::cloud::{ ChatCloudService, ChatMessage, ChatMessageMetadata, ChatMessageType, MessageCursor, @@ -481,9 +484,37 @@ impl Chat { ); self .chat_service - .index_file(&self.user_service.workspace_id()?, file_path, &self.chat_id) + .index_file( + &self.user_service.workspace_id()?, + &file_path, + &self.chat_id, + ) .await?; + let file_name = file_path + .file_name() + .unwrap_or_default() + .to_str() + .unwrap_or_default(); + + let mut conn = self.user_service.sqlite_connection(self.uid)?; + conn.immediate_transaction(|conn| { + let mut metadata = read_chat_metadata(conn, &self.chat_id)?; + metadata.add_file( + file_name.to_string(), + file_path.to_str().unwrap_or_default().to_string(), + ); + let changeset = ChatTableChangeset::from_metadata(metadata); + update_chat(conn, changeset)?; + Ok::<(), FlowyError>(()) + })?; + + trace!( + "[Chat] created index file record: chat_id={}, file_path={:?}", + self.chat_id, + file_path + ); + Ok(()) } } diff --git a/frontend/rust-lib/flowy-ai/src/entities.rs b/frontend/rust-lib/flowy-ai/src/entities.rs index 04ce6c771f..5ff3cd5bd3 100644 --- a/frontend/rust-lib/flowy-ai/src/entities.rs +++ b/frontend/rust-lib/flowy-ai/src/entities.rs @@ -9,6 +9,29 @@ use flowy_ai_pub::cloud::{ use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use lib_infra::validator_fn::required_not_empty_str; use validator::Validate; +#[derive(Default, ProtoBuf, Validate, Clone, Debug)] +pub struct ChatId { + #[pb(index = 1)] + #[validate(custom = "required_not_empty_str")] + pub value: String, +} + +#[derive(Default, ProtoBuf, Clone, Debug)] +pub struct ChatInfoPB { + #[pb(index = 1)] + pub chat_id: String, + + #[pb(index = 2)] + pub files: Vec, +} + +#[derive(Default, ProtoBuf, Clone, Debug)] +pub struct FilePB { + #[pb(index = 1)] + pub id: String, + #[pb(index = 2)] + pub name: String, +} #[derive(Default, ProtoBuf, Validate, Clone, Debug)] pub struct SendChatPayloadPB { @@ -53,7 +76,7 @@ pub struct ChatMessageMetaPB { pub name: String, #[pb(index = 3)] - pub text: String, + pub data: String, #[pb(index = 4)] pub source: String, diff --git a/frontend/rust-lib/flowy-ai/src/event_handler.rs b/frontend/rust-lib/flowy-ai/src/event_handler.rs index 6ca6778c30..dd8e984ee4 100644 --- a/frontend/rust-lib/flowy-ai/src/event_handler.rs +++ b/frontend/rust-lib/flowy-ai/src/event_handler.rs @@ -1,3 +1,4 @@ +use std::fs; use std::path::PathBuf; use crate::ai_manager::AIManager; @@ -39,10 +40,11 @@ pub(crate) async fn stream_chat_message_handler( .metadata .into_iter() .map(|metadata| ChatMessageMetadata { - data: ChatMetadataData::new_text(metadata.text), + data: ChatMetadataData::new_text(metadata.data), id: metadata.id, name: metadata.name.clone(), source: metadata.source, + extract: None, }) .collect::>(); @@ -231,6 +233,24 @@ pub(crate) async fn chat_file_handler( "Only support pdf,md and txt", )); } + let file_size = fs::metadata(&file_path) + .map_err(|_| { + FlowyError::new( + ErrorCode::UnsupportedFileFormat, + "Failed to get file metadata", + ) + })? + .len(); + + const MAX_FILE_SIZE: u64 = 10 * 1024 * 1024; + if file_size > MAX_FILE_SIZE { + return Err(FlowyError::new( + ErrorCode::PayloadTooLarge, + "File size is too large. Max file size is 10MB", + )); + } + + tracing::debug!("File size: {} bytes", file_size); let (tx, rx) = oneshot::channel::>(); tokio::spawn(async move { @@ -406,3 +426,14 @@ pub(crate) async fn create_chat_context_handler( Ok(()) } + +#[tracing::instrument(level = "debug", skip_all, err)] +pub(crate) async fn get_chat_info_handler( + data: AFPluginData, + ai_manager: AFPluginState>, +) -> DataResult { + let chat_id = data.try_into_inner()?.value; + let ai_manager = upgrade_ai_manager(ai_manager)?; + let pb = ai_manager.get_chat_info(&chat_id).await?; + data_result_ok(pb) +} diff --git a/frontend/rust-lib/flowy-ai/src/event_map.rs b/frontend/rust-lib/flowy-ai/src/event_map.rs index e4e9d03b4c..109be1a253 100644 --- a/frontend/rust-lib/flowy-ai/src/event_map.rs +++ b/frontend/rust-lib/flowy-ai/src/event_map.rs @@ -56,6 +56,7 @@ pub fn init(ai_manager: Weak) -> AFPlugin { ) .event(AIEvent::GetOfflineAIAppLink, get_offline_app_handler) .event(AIEvent::CreateChatContext, create_chat_context_handler) + .event(AIEvent::GetChatInfo, create_chat_context_handler) } #[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)] @@ -138,4 +139,7 @@ pub enum AIEvent { #[event(input = "CreateChatContextPB")] CreateChatContext = 23, + + #[event(input = "ChatId", output = "ChatInfoPB")] + GetChatInfo = 24, } diff --git a/frontend/rust-lib/flowy-ai/src/middleware/chat_service_mw.rs b/frontend/rust-lib/flowy-ai/src/middleware/chat_service_mw.rs index 712e452d39..76a961531c 100644 --- a/frontend/rust-lib/flowy-ai/src/middleware/chat_service_mw.rs +++ b/frontend/rust-lib/flowy-ai/src/middleware/chat_service_mw.rs @@ -16,7 +16,7 @@ use lib_infra::async_trait::async_trait; use lib_infra::future::FutureResult; use crate::local_ai::stream_util::LocalAIStreamAdaptor; -use std::path::PathBuf; +use std::path::Path; use std::sync::Arc; pub struct AICloudServiceMiddleware { @@ -242,13 +242,13 @@ impl ChatCloudService for AICloudServiceMiddleware { async fn index_file( &self, workspace_id: &str, - file_path: PathBuf, + file_path: &Path, chat_id: &str, ) -> Result<(), FlowyError> { if self.local_llm_controller.is_running() { self .local_llm_controller - .index_file(chat_id, file_path) + .index_file(chat_id, file_path.to_path_buf()) .await .map_err(|err| FlowyError::local_ai().with_context(err))?; Ok(()) diff --git a/frontend/rust-lib/flowy-ai/src/persistence/chat_sql.rs b/frontend/rust-lib/flowy-ai/src/persistence/chat_sql.rs index 9971713afb..6086c8e466 100644 --- a/frontend/rust-lib/flowy-ai/src/persistence/chat_sql.rs +++ b/frontend/rust-lib/flowy-ai/src/persistence/chat_sql.rs @@ -1,4 +1,5 @@ use diesel::sqlite::SqliteConnection; +use flowy_error::FlowyResult; use flowy_sqlite::upsert::excluded; use flowy_sqlite::{ diesel, @@ -6,6 +7,7 @@ use flowy_sqlite::{ schema::{chat_table, chat_table::dsl}, AsChangeset, DBConnection, ExpressionMethods, Identifiable, Insertable, QueryResult, Queryable, }; +use serde::{Deserialize, Serialize}; #[derive(Clone, Default, Queryable, Insertable, Identifiable)] #[diesel(table_name = chat_table)] @@ -14,24 +16,54 @@ pub struct ChatTable { pub chat_id: String, pub created_at: i64, pub name: String, - pub local_model_path: String, - pub local_model_name: String, + pub local_files: String, + pub metadata: String, pub local_enabled: bool, pub sync_to_cloud: bool, } +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct ChatTableMetadata { + pub files: Vec, +} + +impl ChatTableMetadata { + pub fn add_file(&mut self, name: String, id: String) { + if let Some(file) = self.files.iter_mut().find(|f| f.name == name) { + file.id = id; + } else { + self.files.push(ChatTableFile { name, id }); + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ChatTableFile { + pub name: String, + pub id: String, +} + #[derive(AsChangeset, Identifiable, Default, Debug)] #[diesel(table_name = chat_table)] #[diesel(primary_key(chat_id))] pub struct ChatTableChangeset { pub chat_id: String, pub name: Option, - pub local_model_path: Option, - pub local_model_name: Option, + pub local_files: Option, + pub metadata: Option, pub local_enabled: Option, pub sync_to_cloud: Option, } +impl ChatTableChangeset { + pub fn from_metadata(metadata: ChatTableMetadata) -> Self { + ChatTableChangeset { + metadata: serde_json::to_string(&metadata).ok(), + ..Default::default() + } + } +} + pub fn insert_chat(mut conn: DBConnection, new_chat: &ChatTable) -> QueryResult { diesel::insert_into(chat_table::table) .values(new_chat) @@ -44,8 +76,7 @@ pub fn insert_chat(mut conn: DBConnection, new_chat: &ChatTable) -> QueryResult< .execute(&mut *conn) } -#[allow(dead_code)] -pub fn update_chat_local_model( +pub fn update_chat( conn: &mut SqliteConnection, changeset: ChatTableChangeset, ) -> QueryResult { @@ -62,6 +93,18 @@ pub fn read_chat(mut conn: DBConnection, chat_id_val: &str) -> QueryResult FlowyResult { + let metadata_str = dsl::chat_table + .select(chat_table::metadata) + .filter(chat_table::chat_id.eq(chat_id_val)) + .first::(&mut *conn)?; + let value = serde_json::from_str(&metadata_str).unwrap_or_default(); + Ok(value) +} + #[allow(dead_code)] pub fn update_chat_name( mut conn: DBConnection, diff --git a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs index 0f6d414233..da2d9d41e6 100644 --- a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs +++ b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs @@ -1,6 +1,6 @@ use client_api::entity::search_dto::SearchDocumentResponseItem; use flowy_search_pub::cloud::SearchCloudService; -use std::path::PathBuf; +use std::path::Path; use std::sync::Arc; use anyhow::Error; @@ -729,7 +729,7 @@ impl ChatCloudService for ServerProvider { async fn index_file( &self, workspace_id: &str, - file_path: PathBuf, + file_path: &Path, chat_id: &str, ) -> Result<(), FlowyError> { self diff --git a/frontend/rust-lib/flowy-error/src/code.rs b/frontend/rust-lib/flowy-error/src/code.rs index 9b546d0182..fc12ed4606 100644 --- a/frontend/rust-lib/flowy-error/src/code.rs +++ b/frontend/rust-lib/flowy-error/src/code.rs @@ -257,8 +257,8 @@ pub enum ErrorCode { #[error("AppFlowy data folder import error")] AppFlowyDataFolderImportError = 89, - #[error("Cloud request payload too large")] - CloudRequestPayloadTooLarge = 90, + #[error("payload too large")] + PayloadTooLarge = 90, #[error("Workspace limit exceeded")] WorkspaceLimitExceeded = 91, diff --git a/frontend/rust-lib/flowy-error/src/impl_from/cloud.rs b/frontend/rust-lib/flowy-error/src/impl_from/cloud.rs index a436544e01..c857fc7ec9 100644 --- a/frontend/rust-lib/flowy-error/src/impl_from/cloud.rs +++ b/frontend/rust-lib/flowy-error/src/impl_from/cloud.rs @@ -20,7 +20,7 @@ impl From for FlowyError { AppErrorCode::NotLoggedIn => ErrorCode::UserUnauthorized, AppErrorCode::NotEnoughPermissions => ErrorCode::NotEnoughPermissions, AppErrorCode::NetworkError => ErrorCode::HttpError, - AppErrorCode::PayloadTooLarge => ErrorCode::CloudRequestPayloadTooLarge, + AppErrorCode::PayloadTooLarge => ErrorCode::PayloadTooLarge, AppErrorCode::UserUnAuthorized => ErrorCode::UserUnauthorized, AppErrorCode::WorkspaceLimitExceeded => ErrorCode::WorkspaceLimitExceeded, AppErrorCode::WorkspaceMemberLimitExceeded => ErrorCode::WorkspaceMemberLimitExceeded, diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs index 77a0198a97..ca07dbc285 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs @@ -16,7 +16,7 @@ use lib_infra::async_trait::async_trait; use lib_infra::future::FutureResult; use lib_infra::util::{get_operating_system, OperatingSystem}; use serde_json::json; -use std::path::PathBuf; +use std::path::Path; pub(crate) struct AFCloudChatCloudServiceImpl { pub inner: T, @@ -192,7 +192,7 @@ where async fn index_file( &self, _workspace_id: &str, - _file_path: PathBuf, + _file_path: &Path, _chat_id: &str, ) -> Result<(), FlowyError> { return Err( diff --git a/frontend/rust-lib/flowy-server/src/default_impl.rs b/frontend/rust-lib/flowy-server/src/default_impl.rs index c2fde180d8..22f6688ba9 100644 --- a/frontend/rust-lib/flowy-server/src/default_impl.rs +++ b/frontend/rust-lib/flowy-server/src/default_impl.rs @@ -6,7 +6,7 @@ use flowy_ai_pub::cloud::{ use flowy_error::FlowyError; use lib_infra::async_trait::async_trait; use lib_infra::future::FutureResult; -use std::path::PathBuf; +use std::path::Path; pub(crate) struct DefaultChatCloudServiceImpl; @@ -100,7 +100,7 @@ impl ChatCloudService for DefaultChatCloudServiceImpl { async fn index_file( &self, _workspace_id: &str, - _file_path: PathBuf, + _file_path: &Path, _chat_id: &str, ) -> Result<(), FlowyError> { Err(FlowyError::not_support().with_context("indexing file is not supported in local server.")) diff --git a/frontend/rust-lib/flowy-sqlite/migrations/2024-08-07-093650_chat_metadata/down.sql b/frontend/rust-lib/flowy-sqlite/migrations/2024-08-07-093650_chat_metadata/down.sql new file mode 100644 index 0000000000..d9a93fe9a1 --- /dev/null +++ b/frontend/rust-lib/flowy-sqlite/migrations/2024-08-07-093650_chat_metadata/down.sql @@ -0,0 +1 @@ +-- This file should undo anything in `up.sql` diff --git a/frontend/rust-lib/flowy-sqlite/migrations/2024-08-07-093650_chat_metadata/up.sql b/frontend/rust-lib/flowy-sqlite/migrations/2024-08-07-093650_chat_metadata/up.sql new file mode 100644 index 0000000000..948cf866a7 --- /dev/null +++ b/frontend/rust-lib/flowy-sqlite/migrations/2024-08-07-093650_chat_metadata/up.sql @@ -0,0 +1,4 @@ +-- Your SQL goes here +ALTER TABLE chat_table RENAME COLUMN local_model_path TO local_files; +ALTER TABLE chat_table RENAME COLUMN local_model_name TO metadata; + diff --git a/frontend/rust-lib/flowy-sqlite/src/schema.rs b/frontend/rust-lib/flowy-sqlite/src/schema.rs index b65e026f6a..28d278c6a4 100644 --- a/frontend/rust-lib/flowy-sqlite/src/schema.rs +++ b/frontend/rust-lib/flowy-sqlite/src/schema.rs @@ -26,8 +26,8 @@ diesel::table! { chat_id -> Text, created_at -> BigInt, name -> Text, - local_model_path -> Text, - local_model_name -> Text, + local_files -> Text, + metadata -> Text, local_enabled -> Bool, sync_to_cloud -> Bool, }