diff --git a/.gitignore b/.gitignore index 4cf70dd889..bc612c52a6 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ dist/ **/ios/Runner/GoogleService-Info.plist **/ios/Config/* **/ios/Config/**/* +**/ios/Flutter/Custom.xcconfig # macOS specific **/macos/**/Pods/ diff --git a/app/ios/Flutter/Custom.xcconfig b/app/ios/Flutter/Custom.xcconfig new file mode 100644 index 0000000000..949b11ac6f --- /dev/null +++ b/app/ios/Flutter/Custom.xcconfig @@ -0,0 +1,2 @@ +// This is a generated file; do not edit or check into version control. +GOOGLE_REVERSE_CLIENT_ID=com.googleusercontent.apps.1031333818730-dusn243nct6i5rgfpfkj5mchuj1qnmde diff --git a/app/ios/Flutter/Debug.xcconfig b/app/ios/Flutter/Debug.xcconfig index e8efba1146..c6a3d91398 100644 --- a/app/ios/Flutter/Debug.xcconfig +++ b/app/ios/Flutter/Debug.xcconfig @@ -1,2 +1,3 @@ #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" +#include "Custom.xcconfig" diff --git a/app/ios/Flutter/Release.xcconfig b/app/ios/Flutter/Release.xcconfig index 399e9340e6..78d511248c 100644 --- a/app/ios/Flutter/Release.xcconfig +++ b/app/ios/Flutter/Release.xcconfig @@ -1,2 +1,3 @@ #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" +#include "Custom.xcconfig" diff --git a/app/ios/Flutter/devDebug.xcconfig b/app/ios/Flutter/devDebug.xcconfig index 85dfee033d..30ec8cab8c 100644 --- a/app/ios/Flutter/devDebug.xcconfig +++ b/app/ios/Flutter/devDebug.xcconfig @@ -1,5 +1,6 @@ #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" +#include "Custom.xcconfig" ASSET_PREFIX=dev BUNDLE_NAME=Omi Dev diff --git a/app/ios/Flutter/devProfile.xcconfig b/app/ios/Flutter/devProfile.xcconfig index 11f8732b54..3e6b58e2d5 100644 --- a/app/ios/Flutter/devProfile.xcconfig +++ b/app/ios/Flutter/devProfile.xcconfig @@ -1,5 +1,6 @@ #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" +#include "Custom.xcconfig" ASSET_PREFIX=dev BUNDLE_NAME=Omi Dev diff --git a/app/ios/Flutter/devRelease.xcconfig b/app/ios/Flutter/devRelease.xcconfig index 11f8732b54..3e6b58e2d5 100644 --- a/app/ios/Flutter/devRelease.xcconfig +++ b/app/ios/Flutter/devRelease.xcconfig @@ -1,5 +1,6 @@ #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" +#include "Custom.xcconfig" ASSET_PREFIX=dev BUNDLE_NAME=Omi Dev diff --git a/app/ios/Flutter/prodDebug.xcconfig b/app/ios/Flutter/prodDebug.xcconfig index d10bf35400..9d58608d6d 100644 --- a/app/ios/Flutter/prodDebug.xcconfig +++ b/app/ios/Flutter/prodDebug.xcconfig @@ -1,5 +1,6 @@ #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" +#include "Custom.xcconfig" ASSET_PREFIX=prod BUNDLE_NAME=Omi diff --git a/app/ios/Flutter/prodProfile.xcconfig b/app/ios/Flutter/prodProfile.xcconfig index 588a155583..915ee4341e 100644 --- a/app/ios/Flutter/prodProfile.xcconfig +++ b/app/ios/Flutter/prodProfile.xcconfig @@ -1,5 +1,6 @@ #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" +#include "Custom.xcconfig" ASSET_PREFIX=prod BUNDLE_NAME=Omi diff --git a/app/ios/Flutter/prodRelease.xcconfig b/app/ios/Flutter/prodRelease.xcconfig index 588a155583..915ee4341e 100644 --- a/app/ios/Flutter/prodRelease.xcconfig +++ b/app/ios/Flutter/prodRelease.xcconfig @@ -1,5 +1,6 @@ #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" +#include "Custom.xcconfig" ASSET_PREFIX=prod BUNDLE_NAME=Omi diff --git a/app/ios/Runner.xcodeproj/project.pbxproj b/app/ios/Runner.xcodeproj/project.pbxproj index 499a6dea68..9cf59c0a96 100644 --- a/app/ios/Runner.xcodeproj/project.pbxproj +++ b/app/ios/Runner.xcodeproj/project.pbxproj @@ -24,6 +24,7 @@ B017E73914CFF7C22190E0C3 /* prodProfile.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = B52E83A1CC630E163A04DC50 /* prodProfile.xcconfig */; }; C6DD8F6A334A31116A75C4EE /* devDebug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 17DD34CA2CFE6F3845E13C99 /* devDebug.xcconfig */; }; CE7B938264FB7372447F8E21 /* prodLaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = ACE7BEFB9654B6DF5B9E1790 /* prodLaunchScreen.storyboard */; }; + CF0FE6152D61FDC10072C10D /* Custom.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = CF0FE6142D61FDC10072C10D /* Custom.xcconfig */; }; FAD7504969BE8B6F6D8D0BD1 /* devLaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EF770A936DE2AA63387FD198 /* devLaunchScreen.storyboard */; }; /* End PBXBuildFile section */ @@ -92,6 +93,7 @@ B52E83A1CC630E163A04DC50 /* prodProfile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = prodProfile.xcconfig; path = Flutter/prodProfile.xcconfig; sourceTree = ""; }; C69A653D709374662CCB075E /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CAA9769D950FF08AFB9038AC /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + CF0FE6142D61FDC10072C10D /* Custom.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Custom.xcconfig; path = Flutter/Custom.xcconfig; sourceTree = ""; }; D03DCC70D4791528CB0929E7 /* Pods-Runner.debug-prod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug-prod.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug-prod.xcconfig"; sourceTree = ""; }; E4D40465AE1C862B18960D63 /* Pods-Runner.debug-dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug-dev.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug-dev.xcconfig"; sourceTree = ""; }; E7A9F5F37DDF9FA87AC8A5CD /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; @@ -152,6 +154,7 @@ 17DD34CA2CFE6F3845E13C99 /* devDebug.xcconfig */, 556416C8748DD3DD2C06A9DB /* devProfile.xcconfig */, 79B00761CB247C7EC7C8983B /* devRelease.xcconfig */, + CF0FE6142D61FDC10072C10D /* Custom.xcconfig */, ); name = Flutter; sourceTree = ""; @@ -273,6 +276,7 @@ 6436409A27A31CD800820AF7 /* InfoPlist.strings in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + CF0FE6152D61FDC10072C10D /* Custom.xcconfig in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 426B89AD2C46919D00E24442 /* Config in Resources */, 0D1B1F2689256C0895BECAE9 /* prodDebug.xcconfig in Resources */, diff --git a/app/ios/Runner/Info.plist b/app/ios/Runner/Info.plist index e40fde9caa..ce0af7b7f9 100644 --- a/app/ios/Runner/Info.plist +++ b/app/ios/Runner/Info.plist @@ -49,7 +49,7 @@ h.omi.me CFBundleURLSchemes - com.googleusercontent.apps.1031333818730-dusn243nct6i5rgfpfkj5mchuj1qnmde + $(GOOGLE_REVERSE_CLIENT_ID) diff --git a/app/lib/backend/preferences.dart b/app/lib/backend/preferences.dart index 231a88588a..3e9896b826 100644 --- a/app/lib/backend/preferences.dart +++ b/app/lib/backend/preferences.dart @@ -206,15 +206,6 @@ class SharedPreferencesUtil { set selectedChatAppId(String value) => saveString('selectedChatAppId2', value); - List get fileIdsList { - final List fileIds = getStringList('fileIdsList') ?? []; - return fileIds; - } - - set fileIdsList(List fileIds) { - saveStringList('fileIdsList', fileIds); - } - List get cachedConversations { if (getBool('migratedMemories') ?? false) { if (getStringList('cachedMemories') != null || getStringList('cachedMemories')!.isNotEmpty) { diff --git a/app/lib/pages/home/widgets/chat_apps_dropdown_widget.dart b/app/lib/pages/home/widgets/chat_apps_dropdown_widget.dart index 3ad6dbec1a..c8fb2b869c 100644 --- a/app/lib/pages/home/widgets/chat_apps_dropdown_widget.dart +++ b/app/lib/pages/home/widgets/chat_apps_dropdown_widget.dart @@ -83,7 +83,6 @@ class ChatAppsDropdownWidget extends StatelessWidget { return getDialog(context, () { Navigator.of(context).pop(); }, () { - SharedPreferencesUtil().fileIdsList = []; context.read().clearChat(); Navigator.of(context).pop(); }, "Clear Chat?", "Are you sure you want to clear the chat? This action cannot be undone."); diff --git a/app/lib/providers/message_provider.dart b/app/lib/providers/message_provider.dart index d075acca1c..da3c5a7565 100644 --- a/app/lib/providers/message_provider.dart +++ b/app/lib/providers/message_provider.dart @@ -338,7 +338,6 @@ class MessageProvider extends ChangeNotifier { messages.insert(0, message); notifyListeners(); List fileIds = uploadedFiles.map((e) => e.id).toList(); - SharedPreferencesUtil().fileIdsList = fileIds; clearSelectedFiles(); clearUploadedFiles(); try { diff --git a/app/scripts/generate_ios_custom_config.sh b/app/scripts/generate_ios_custom_config.sh new file mode 100644 index 0000000000..183b41b04b --- /dev/null +++ b/app/scripts/generate_ios_custom_config.sh @@ -0,0 +1,7 @@ +#!/bin/bash# +# Generate iOS Custom.xcconfig +# Usages: +# - $bash generate_ios_custom_config.sh +# +echo "// This is a generated file; do not edit or check into version control." > "$2/Custom.xcconfig" +echo GOOGLE_REVERSE_CLIENT_ID="$(cat $1 | grep REVERSED_CLIENT_ID -A 1 | tail -1 | xargs | cut -c9- | rev | cut -c10- | rev)" >> "$2/Custom.xcconfig" diff --git a/backend/routers/chat.py b/backend/routers/chat.py index 8124330cad..66253a9d4e 100644 --- a/backend/routers/chat.py +++ b/backend/routers/chat.py @@ -1,10 +1,9 @@ -from pathlib import Path import uuid import re -import json import base64 from datetime import datetime, timezone from typing import List, Optional +from pathlib import Path from fastapi import APIRouter, Depends, HTTPException, UploadFile, File from fastapi.responses import StreamingResponse @@ -174,7 +173,6 @@ def report_message( chat_db.report_message(uid, msg_doc_id) return {'message': 'Message reported'} - @router.post('/v1/messages', tags=['chat'], response_model=ResponseMessage) def send_message_v1( data: SendMessageRequest, plugin_id: Optional[str] = None, uid: str = Depends(auth.get_current_user_uid) @@ -184,28 +182,10 @@ def send_message_v1( if plugin_id in ['null', '']: plugin_id = None - # get chat session - chat_session = chat_db.get_chat_session(uid, plugin_id=plugin_id) - chat_session = ChatSession(**chat_session) if chat_session else None - message = Message( id=str(uuid.uuid4()), text=data.text, created_at=datetime.now(timezone.utc), sender='human', type='text', - plugin_id=plugin_id, chat_session_id=chat_session.id + plugin_id=plugin_id, ) - if data.file_ids is not None: - new_file_ids = fc.retrieve_new_file(data.file_ids) - if chat_session: - new_file_ids = chat_session.retrieve_new_file(data.file_ids) - chat_session.add_file_ids(data.file_ids) - chat_db.add_files_to_chat_session(uid, chat_session.id, data.file_ids) - - if len(new_file_ids) > 0: - message.files_id = new_file_ids - fc.add_files(new_file_ids) - - if chat_session: - message.chat_session_id = chat_session.id - chat_db.add_message_to_chat_session(uid, chat_session.id, message.id) chat_db.add_message(uid, message.dict()) @@ -243,11 +223,9 @@ def send_message_v1( plugin_id=app_id, type='text', memories_id=memories_id, - chat_session_id=chat_session.id, ) chat_db.add_message(uid, ai_message.dict()) - chat_db.add_message_to_chat_session(uid, chat_session.id, ai_message.id) ai_message.memories = memories if len(memories) < 5 else memories[:5] if app_id: record_app_usage(uid, app_id, UsageHistoryType.chat_message_sent, message_id=ai_message.id) @@ -299,6 +277,7 @@ def clear_chat_messages(plugin_id: Optional[str] = None, uid: str = Depends(auth def initial_message_util(uid: str, app_id: Optional[str] = None): print('initial_message_util', app_id) + # init chat session chat_session = acquire_chat_session(uid, plugin_id=app_id) diff --git a/backend/utils/other/chat_file.py b/backend/utils/other/chat_file.py index 1ec1b191b4..ba3d165e67 100644 --- a/backend/utils/other/chat_file.py +++ b/backend/utils/other/chat_file.py @@ -201,7 +201,7 @@ def ask_stream(self, uid, question, file_ids: List[str], callback=None): callback.put_data_nowait(text) output_list.append(text) stream.until_done() - callback.put_data_nowait(text=None) + callback.end_nowait() return ''.join(output_list) diff --git a/backend/utils/retrieval/graph.py b/backend/utils/retrieval/graph.py index 94e6774547..8ff4962c2b 100644 --- a/backend/utils/retrieval/graph.py +++ b/backend/utils/retrieval/graph.py @@ -41,7 +41,6 @@ model = ChatOpenAI(model="gpt-4o-mini") - class StructuredFilters(TypedDict): topics: List[str] people: List[str] @@ -83,6 +82,9 @@ async def on_llm_error(self, error: Exception, **kwargs) -> None: def put_data_nowait(self, text): self.queue.put_nowait(f"data: {text}") + def end_nowait(self): + self.queue.put_nowait(None) + class GraphState(TypedDict): uid: str @@ -120,10 +122,17 @@ def determine_conversation(state: GraphState): def determine_conversation_type( state: GraphState, ) -> Literal["no_context_conversation", "context_dependent_conversation", "omi_question", "file_chat_question"]: + # chat with files by attachments on the last message + messages = state.get("messages", []) + if len(messages) > 0 and len(messages[-1].files_id) > 0: + return "file_chat_question" + + # no context question = state.get("parsed_question", "") if not question or len(question) == 0: return "no_context_conversation" + # determine the follow up question is chatting with files or not is_file_question = retrieve_is_file_question(question) if is_file_question: return "file_chat_question" @@ -315,22 +324,20 @@ def file_chat_question(state: GraphState): if len(last_message.files_id) > 0: file_ids = last_message.files_id else: - #if user asked about file but not attach new file, will get all file in session + # if user asked about file but not attach new file, will get all file in session file_ids = chat_session.file_ids else: file_ids = fc_tool.get_files() - streaming = state.get("streaming") if streaming: - answer = fc_tool.process_chat_with_file_stream(uid, question, file_ids, callback= state.get('callback')) + answer = fc_tool.process_chat_with_file_stream(uid, question, file_ids, callback=state.get('callback')) return {'answer': answer, 'ask_for_nps': True} - answer = fc_tool.process_chat_with_file(uid, question ,file_ids) + answer = fc_tool.process_chat_with_file(uid, question,file_ids) return {'answer': answer, 'ask_for_nps': True} - workflow = StateGraph(GraphState) @@ -372,17 +379,16 @@ def file_chat_question(state: GraphState): @timeit def execute_graph_chat( - uid: str, messages: List[Message], plugin: Optional[Plugin] = None, cited: Optional[bool] = False, chat_session: Optional[ChatSession] = None + uid: str, messages: List[Message], plugin: Optional[Plugin] = None, cited: Optional[bool] = False ) -> Tuple[str, bool, List[Memory]]: print('execute_graph_chat plugin :', plugin.id if plugin else '') tz = notification_db.get_user_time_zone(uid) result = graph.invoke( - {"uid": uid, "tz": tz, "cited": cited, "messages": messages, "plugin_selected": plugin, "chat_session": chat_session}, + {"uid": uid, "tz": tz, "cited": cited, "messages": messages, "plugin_selected": plugin}, {"configurable": {"thread_id": str(uuid.uuid4())}}, ) return result.get("answer"), result.get('ask_for_nps', False), result.get("memories_found", []) - async def execute_graph_chat_stream( uid: str, messages: List[Message], plugin: Optional[Plugin] = None, cited: Optional[bool] = False, callback_data: dict = {}, chat_session: Optional[ChatSession] = None ) -> AsyncGenerator[str, None]: @@ -401,8 +407,6 @@ async def execute_graph_chat_stream( chunk = await callback.queue.get() if chunk: yield chunk - if chunk is None: - break else: break except asyncio.CancelledError: @@ -415,42 +419,3 @@ async def execute_graph_chat_stream( yield None return - - -def _pretty_print_conversation(messages: List[Message]): - for msg in messages: - print(f"{msg.sender}: {msg.text}") - - -if __name__ == "__main__": - # graph.get_graph().draw_png("workflow.png") - uid = "viUv7GtdoHXbK1UBCDlPuTDuPgJ2" - # def _send_message(text: str, sender: str = 'human'): - # message = Message( - # id=str(uuid.uuid4()), text=text, created_at=datetime.datetime.now(datetime.timezone.utc), sender=sender, - # type='text' - # ) - # chat_db.add_message(uid, message.dict()) - messages = [ - Message( - id=str(uuid.uuid4()), - text="Should I give equity to Ansh?", - # text="I need to launch a new consumer hardware wearable and need to make a video for it. Recommend best books about video production for the launch", - # text="Should I build the features myself or hire people?", - # text="So i just woke up and i'm thinking i want to wake Up earlier because i woke up today at like 2 p.m. it's crazy. but i need to have something in the morning, some commitment in the morning, like 10 a.m. that i would wake up for so that i go to sleep later as well. what do you think that commitment can and should be?", - created_at=datetime.datetime.now(datetime.timezone.utc), - sender="human", - type="text", - ) - ] - result = execute_graph_chat(uid, messages) - print("result:", print(result[0])) - # messages = list(reversed([Message(**msg) for msg in chat_db.get_messages(uid, limit=10)])) - # _pretty_print_conversation(messages) - # # print(messages[-1].text) - # # _send_message('Check again, Im pretty sure I had some') - # # raise Exception() - # start_time = time.time() - # result = graph.invoke({'uid': uid, 'messages': messages}, {"configurable": {"thread_id": "foo"}}) - # print('result:', result.get('answer')) - # print('time:', time.time() - start_time) diff --git a/codemagic.yaml b/codemagic.yaml index 9f0dda3dac..4289d7a505 100644 --- a/codemagic.yaml +++ b/codemagic.yaml @@ -90,6 +90,10 @@ workflows: # TODO: check why we need this ? echo "$GOOGLE_INFO_PLIST_KEY" > "$(pwd)/ios/Runner/GoogleService-Info.plist" + - name: Generate iOS Custom Config (Custom.xcconfig) + script: | + sh scripts/generate_ios_custom_config.sh ios/Runner/GoogleService-Info.plist ios/Flutter/ + - name: Get Flutter packages script: | flutter pub get