diff --git a/ios/voicebox.xcodeproj/project.pbxproj b/ios/voicebox.xcodeproj/project.pbxproj index 18e15ff..7dc49ea 100644 --- a/ios/voicebox.xcodeproj/project.pbxproj +++ b/ios/voicebox.xcodeproj/project.pbxproj @@ -693,7 +693,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.3; + MARKETING_VERSION = 1.0.4; PRODUCT_BUNDLE_IDENTIFIER = net.scosman.voicebox; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; @@ -723,7 +723,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.3; + MARKETING_VERSION = 1.0.4; PRODUCT_BUNDLE_IDENTIFIER = net.scosman.voicebox; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; diff --git a/ios/voicebox/UI/VBShareViewController.m b/ios/voicebox/UI/VBShareViewController.m index 2f55697..8afcead 100644 --- a/ios/voicebox/UI/VBShareViewController.m +++ b/ios/voicebox/UI/VBShareViewController.m @@ -143,6 +143,8 @@ - (void)showSendEmail:(NSString*)body withSubject:(NSString*)subject // Mailto required /r/n body = [body stringByReplacingOccurrencesOfString:@"\n" withString:@"\r\n"]; + NSLog(@"Subject: %@", subject); + NSURLComponents* urlComps = [NSURLComponents componentsWithString:@"mailto:"]; urlComps.queryItems = @[ [NSURLQueryItem queryItemWithName:@"body" @@ -159,12 +161,14 @@ - (void)showSendEmail:(NSString*)body withSubject:(NSString*)subject if (success) { [self dismissViewControllerAnimated:YES completion:nil]; } else { - UIAlertController* errVC = [UIAlertController alertControllerWithTitle:@"Error Launching Email" message:@"We could not launch your default email application." preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" - style:UIAlertActionStyleDefault - handler:nil]; - [errVC addAction:defaultAction]; - [self presentViewController:errVC animated:YES completion:nil]; + dispatch_async(dispatch_get_main_queue(), ^{ + UIAlertController* errVC = [UIAlertController alertControllerWithTitle:@"Error Launching Email" message:@"We could not launch your default email application." preferredStyle:UIAlertControllerStyleAlert]; + UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" + style:UIAlertActionStyleDefault + handler:nil]; + [errVC addAction:defaultAction]; + [self presentViewController:errVC animated:YES completion:nil]; + }); } }]; }); diff --git a/ios/voicebox/Util/OpenAiApiRequest.m b/ios/voicebox/Util/OpenAiApiRequest.m index f58c77c..a1a3e90 100644 --- a/ios/voicebox/Util/OpenAiApiRequest.m +++ b/ios/voicebox/Util/OpenAiApiRequest.m @@ -208,7 +208,7 @@ - (NSMutableDictionary*)buildBodyForChatCompletion:(ChatGptRequest*)request strangely it's been rock solid, so using for prototyping. Try the "n" param of open API endpoint, and structured response instead of parsing json from plaintext */ -- (NSString*)sendSynchronousRequestRaw:(NSError**)error +- (id)sendSynchronousRequestRaw:(NSError**)error { NSData* bodyPayloadJsonData = [NSJSONSerialization dataWithJSONObject:self.bodyPayload options:NSJSONWritingPrettyPrinted error:error]; if (*error) { @@ -280,30 +280,28 @@ - (NSString*)sendSynchronousRequestRaw:(NSError**)error *error = [self apiError:89345]; return nil; } + NSLog(@"Raw string: %@", responseMessage); - return responseMessage; + NSString* jsonString = [OpenAiApiRequest extractJsonBlockFromStringMsg:responseMessage]; + NSData* jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; + id json = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&jsonError]; + if (jsonError) { + *error = jsonError; + return nil; + } + NSLog(@"Parsed JSON: %@", json); + + return json; } - (NSMutableArray*)sendSynchronousRequest:(NSError**)error { - NSString* openAiMessage = [self sendSynchronousRequestRaw:error]; - return [OpenAiApiRequest processMessageString:openAiMessage withError:error]; + id responseJson = [self sendSynchronousRequestRaw:error]; + return [OpenAiApiRequest processMessageString:responseJson withError:error]; } -+ (NSMutableArray*)processMessageString:(NSString*)msgString withError:(NSError**)error ++ (NSMutableArray*)processMessageString:(id)options withError:(NSError**)error { - NSLog(@"%@", msgString); - NSString* jsonString = [self extractJsonBlockFromStringMsg:msgString]; - NSLog(@"%@", jsonString); - - NSData* jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; - NSError* jsonError = nil; - id options = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&jsonError]; - if (jsonError) { - *error = jsonError; - return nil; - } - NSMutableArray* optionArray = [[NSMutableArray alloc] init]; if ([options isKindOfClass:[NSArray class]]) { for (id option in (NSArray*)options) { diff --git a/ios/voicebox/Util/VBMagicEnhancer.m b/ios/voicebox/Util/VBMagicEnhancer.m index be45e8e..61e8582 100644 --- a/ios/voicebox/Util/VBMagicEnhancer.m +++ b/ios/voicebox/Util/VBMagicEnhancer.m @@ -52,7 +52,7 @@ - (void)generateSubjectForEmail:(NSString*)emailText onComplete:(void (^)(NSStri ChatGptMessage* apiMessage = [[ChatGptMessage alloc] init]; apiMessage.roll = kChatGptRollUser; - apiMessage.content = emailText; + apiMessage.content = [NSString stringWithFormat:@"The email body is as follows:\n\n%@", emailText]; request.messages = @[ apiMessage ]; OpenAiApiRequest* req = [self buildApiRequest:request]; @@ -65,12 +65,23 @@ - (void)generateSubjectForEmail:(NSString*)emailText onComplete:(void (^)(NSStri dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ NSError* err; - NSString* subject = [req sendSynchronousRequestRaw:&err]; + id json = [req sendSynchronousRequestRaw:&err]; if (err) { complete(nil, err); - } else { - complete(subject, nil); + return; + } + if (![json isKindOfClass:[NSDictionary class]]) { + complete(nil, err); + return; } + NSDictionary* jsonDict = (NSDictionary*)json; + id subject = jsonDict[@"subject"]; + if (![subject isKindOfClass:[NSString class]]) { + complete(nil, err); + return; + } + + complete((NSString*)subject, nil); }); } @@ -328,7 +339,7 @@ - (NSString*)gpt3NextSentancePromptTemplate - (NSString*)emailSubjectPrompt { - return @"You are a useful assistant which generates friendly email subjects, given an email body.\n\nEvery user message is a user email body, to which you should reply with a suggested subject.\n\n - The suggested subject should be brief. 2 to 8 words is ideal. Never over 12 words.\n - The suggested subject should not try to repeat the email content or all topics, but just give a nice subject to identify the emails from others\n - Your reply should contain only a single suggested subject. It should not contain any prefixes (\"Suggested email subject: \", etc), and formatting (list formatting, etc), alternative suggestions, or descriptions of your sugesstion."; + return @"You are a useful assistant which generates friendly email subjects, given an email body.\n\nEvery user message is a user email body, to which you should reply with a suggested subject (in JSON format, described below).\n\n - The suggested subject should be brief. 2 to 8 words is ideal. Never over 12 words.\n - The suggested subject should not try to repeat the email content or all topics, but just give a nice subject to identify the emails from others\n - The subject should be friendly and use plain language. For example 'question' is better than 'inquiry'.\n - You must not not guess information that isn't clearly included from the email body, or request string replacement such as '[More Data]'. If there's not enough information in the email body to generate a useful subject (and only in that case), return the exact string 'Email from Bryan' as the subject line in the JSON (this exact string, including the name Bryan, as the user's name is Bryan).\n\nYour response should be formatted as follows:\n1) First include a short 1-3 sentence description of the subject line and why it was chosen.\n2) The answer to this step must be JSON formatted and wrapped in triple backtick quotes. The root of the JSON structure is an object/map, which contains a single key 'subject', whose value is the subject line as a string. The response will be parsed by an application, and expects this exact format, so failure to produce a valid JSON response is a complete failure. As an example of valid json is as follows: ```json\n{\"subject\": \"Email from Bryan\"}\n```\n\n"; } @end diff --git a/ios/voicebox/Util/VBResponseOption.h b/ios/voicebox/Util/VBResponseOption.h index 187a6a4..1b9e399 100644 --- a/ios/voicebox/Util/VBResponseOption.h +++ b/ios/voicebox/Util/VBResponseOption.h @@ -23,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN @protocol VBMLProvider -- (NSString*)sendSynchronousRequestRaw:(NSError**)error; +- (id)sendSynchronousRequestRaw:(NSError**)error; // return parsed json (dict) - (NSMutableArray*)sendSynchronousRequest:(NSError**)error; @end