separated request class

This commit is contained in:
Santiago Lema 2025-05-07 06:31:50 -03:00
parent 2dd76e787e
commit c8523bc115
8 changed files with 336 additions and 209 deletions

View file

@ -5,9 +5,7 @@
#include "MainWindow.h"
#include <cstring>
#include <Url.h>
#include <Application.h>
#include <Button.h>
@ -18,23 +16,10 @@
#include <MimeType.h>
#include <ScrollView.h>
#include <StringView.h>
#include <memory.h>
#include <View.h>
#include <File.h>
#include <FindDirectory.h>
#include <Path.h>
#include <String.h>
#include <iostream>
#include <algorithm>
#include <cstdio>
#include "include/json.hpp"
using json = nlohmann::json;
using namespace BPrivate::Network;
#include "Conversation.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "Window"
@ -50,6 +35,13 @@ MainWindow::MainWindow()
: BWindow(BRect(100, 100, 600, 400), B_TRANSLATE("BeDumb"), B_TITLED_WINDOW,
B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE) {
//Without this conversation would never get bmessages from HttpRequest
LockLooper();
AddHandler(_conversation);
UnlockLooper();
BMenuBar *menuBar = _BuildMenu();
BLayoutBuilder::Group<>(this, B_VERTICAL, 0).Add(menuBar).AddGlue().End();
@ -87,8 +79,6 @@ MainWindow::MainWindow()
float askH = lineHeight * 5;
_inputField->SetExplicitMinSize(BSize(B_SIZE_UNSET, askH));
_apiKey = ReadOpenAIKey();
printf("key is: %s", _apiKey.String());
BButton *sendButton =
new BButton("send", B_TRANSLATE("Send"), new BMessage(kSendPrompt),
@ -130,7 +120,7 @@ MainWindow::~MainWindow() {}
void MainWindow::MessageReceived(BMessage *message) {
switch (message->what) {
switch (message->what) {
// case kMsgNewFile: {
// fSaveMenuItem->SetEnabled(false);
@ -148,101 +138,38 @@ void MainWindow::MessageReceived(BMessage *message) {
case kSendPrompt: {
printf("Button Pressed\n");
sendQuery();
} break;
case UrlEvent::HostNameResolved: {
printf("Host name resolved\n");
auto name = message->GetString(UrlEventData::HostName);
message->PrintToStream();
_infoView->SetText("Hostname resolve...");
_infoView->SetText(name);
_progress->SetMaxValue(100);
_progress->SetTo(5);
printf("Button Pressed\n");
_infoView->SetText("Asking...");
_conversation->ask(std::string(_inputField->Text()));
} break;
case UrlEvent::ConnectionOpened: {
printf("ConnectionOpened\n");
_progress->SetTo(10);
_infoView->SetText("connection opened...");
} break;
case kSendReply: {
printf("Conversation returned!\n");
_infoView->SetText("Answer Received");
case UrlEvent::ResponseStarted: {
printf("ResponseStarted\n");
_progress->SetTo(14);
_infoView->SetText("ResponseStarted...");
} break;
case UrlEvent::HttpRedirect: {
printf("HttpRedirect\n");
_progress->SetTo(16);
_infoView->SetText("HttpRedirect...");
} break;
case UrlEvent::RequestCompleted: {
printf("RequestCompleted\n");
auto identifier = message->GetInt32(UrlEventData::Id, -1);
if (_lastResult->Identity() == identifier) {
// The following call will not block, because we have been notified
// that the request is done.
BHttpBody body = _lastResult->Body();
if (body.text.has_value())
{
json parsed = json::parse(body.text.value().String());
std::string content = parsed["choices"][0]["message"]["content"];
_answerView->SetText(content.c_str());
// _answerView->SetText(body.text.value());
}
else
_answerView->SetText("nuthin'");
}
_infoView->SetText("Completed");
const char* text;
if (message->FindString("text", &text) == B_OK) {
printf("Received text: %s\n", text);
// Do something with text (e.g., set it to a BTextView)
_answerView->SetText(text);
} else {
printf("No text found in message.\n");
_answerView->SetText("NO TEXT IN REPLY");
}
_progress->SetMaxValue(100);
_progress->SetTo(100);
} break;
case UrlEvent::HttpStatus: {
printf("HttpStatus\n");
_infoView->SetText("HttpStatus received");
_progress->SetTo(20);
} break;
case UrlEvent::BytesWritten: {
_infoView->SetText("Some bytes written..");
auto identifier = message->GetInt32(UrlEventData::Id, -1);
if (_lastResult->Identity() == identifier) {
off_t numBytes = message->GetInt64(UrlEventData::NumBytes, 0);
off_t totalBytes = message->GetInt64(UrlEventData::TotalBytes, 0);
_progress->SetTo(numBytes);
_progress->SetMaxValue(totalBytes);
}
} break;
case UrlEvent::DownloadProgress: {
auto identifier = message->GetInt32(UrlEventData::Id, -1);
if (_lastResult->Identity() == identifier) {
off_t nn = message->GetInt64(UrlEventData::NumBytes, 0);
off_t totalBytes = message->GetInt64(UrlEventData::TotalBytes, 0);
_progress->SetTo(nn);
_progress->SetMaxValue(totalBytes);
_infoView->SetText("Download Progress..");
}
} break;
default: {
// message->PrintToStream();
BWindow::MessageReceived(
BHandler::MessageReceived(
message); // call the parent handler for other messages
// _infoView->SetText(message->FindMessage());
break;
@ -252,51 +179,6 @@ void MainWindow::MessageReceived(BMessage *message) {
} // end function
void MainWindow::sendQuery() {
if (_lastResult)
_sharedSession.Cancel(_lastResult->Identity());
_progress->SetMaxValue(100);
_progress->SetTo(0);
auto url = BUrl("https://api.openai.com/v1/chat/completions");
BHttpRequest request = BHttpRequest(url);
request.SetMethod(BHttpMethod::Post);
// if the API key file contains a new line bhttpfields will crash with invalid
// content .end() requires include algorithm
std::string key = _apiKey.String();
key.erase(std::remove(key.begin(), key.end(), '\n'), key.end());
key.erase(std::remove(key.begin(), key.end(), '\r'), key.end());
std::string bearer = std::string("Bearer ") + std::string(key);
BHttpFields fields = BHttpFields();
fields.AddField("Authorization", bearer);
// fields.AddField("Content-Type", "application/json"); //NO, this will
// crash, we set it in request
request.SetFields(fields);
json bodyJson = {
{"model", "gpt-3.5-turbo"},
{"messages", {{{"role", "user"}, {"content", _inputField->Text()}}}}};
std::string body = bodyJson.dump();
BString mime = BString("application/json");
// request.SetRequestBody(body.c_str(),mime);
auto memoryIO = std::make_unique<BMemoryIO>(body.c_str(), body.size());
request.SetRequestBody(std::move(memoryIO), "application/json", body.size());
printf("Sending Prompt to server: %s\n", url.UrlString().String());
_lastResult = _sharedSession.Execute(std::move(request), nullptr, this);
if (_lastResult) {
printf("Result has identity: %d\n", _lastResult->Identity());
}
}
BMenuBar *MainWindow::_BuildMenu() {
@ -336,32 +218,3 @@ BMenuBar *MainWindow::_BuildMenu() {
}
BString MainWindow::ReadOpenAIKey() {
// /boot/home/config/openai_key
// or ~/.config/openai_key on linux
BPath configPath;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &configPath) != B_OK)
return "error: couldn't find config directory";
configPath.Append("openai_key");
BFile file(configPath.Path(), B_READ_ONLY);
printf("full path:%s\n", configPath.Path());
if (file.InitCheck() != B_OK)
return "error: couldn't open key file ";
off_t size;
file.GetSize(&size);
char *buffer = new char[size + 1];
file.Read(buffer, size);
buffer[size] = '\0'; // null-terminate
BString result(buffer);
delete[] buffer;
return result;
}