Skip to content
This repository was archived by the owner on Jul 4, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions engine/common/file.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#pragma once

#include <string>
#include "common/json_serializable.h"

namespace OpenAi {
/**
* The File object represents a document that has been uploaded to OpenAI.
*/
struct File : public JsonSerializable {
/**
* The file identifier, which can be referenced in the API endpoints.
*/
std::string id;

/**
* The object type, which is always file.
*/
std::string object = "file";

/**
* The size of the file, in bytes.
*/
uint64_t bytes;

/**
* The Unix timestamp (in seconds) for when the file was created.
*/
uint32_t created_at;

/**
* The name of the file.
*/
std::string filename;

/**
* The intended purpose of the file. Supported values are assistants,
* assistants_output, batch, batch_output, fine-tune, fine-tune-results
* and vision.
*/
std::string purpose;

~File() = default;

static cpp::result<File, std::string> FromJson(const Json::Value& json) {
File file;

file.id = std::move(json["id"].asString());
file.object = "file";
file.bytes = json["bytes"].asUInt64();
file.created_at = json["created_at"].asUInt();
file.filename = std::move(json["filename"].asString());
file.purpose = std::move(json["purpose"].asString());

return file;
}

cpp::result<Json::Value, std::string> ToJson() {
Json::Value root;

root["id"] = id;
root["object"] = object;
root["bytes"] = bytes;
root["created_at"] = created_at;
root["filename"] = filename;
root["purpose"] = purpose;

return root;
}
};
} // namespace OpenAi
69 changes: 68 additions & 1 deletion engine/common/message.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@

namespace OpenAi {

inline std::string ExtractFileId(const std::string& path) {
// Handle both forward and backward slashes
auto last_slash = path.find_last_of("/\\");
if (last_slash == std::string::npos)
return "";

auto filename = path.substr(last_slash + 1);
auto dot_pos = filename.find('.');
if (dot_pos == std::string::npos)
return "";

return filename.substr(0, dot_pos);
}

// Represents a message within a thread.
struct Message : JsonSerializable {
Message() = default;
Expand Down Expand Up @@ -70,6 +84,12 @@ struct Message : JsonSerializable {
// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maximum of 512 characters long.
Cortex::VariantMap metadata;

// deprecated. remove in the future
std::optional<std::string> attach_filename;
std::optional<uint64_t> size;
std::optional<std::string> rel_path;
// end deprecated

static cpp::result<Message, std::string> FromJsonString(
std::string&& json_str) {
Json::Value root;
Expand Down Expand Up @@ -98,7 +118,6 @@ struct Message : JsonSerializable {
message.completed_at = root["completed_at"].asUInt();
message.incomplete_at = root["incomplete_at"].asUInt();
message.role = RoleFromString(std::move(root["role"].asString()));
message.content = ParseContents(std::move(root["content"])).value();

message.assistant_id = std::move(root["assistant_id"].asString());
message.run_id = std::move(root["run_id"].asString());
Expand All @@ -114,6 +133,54 @@ struct Message : JsonSerializable {
}
}

if (root.isMember("content")) {
if (root["content"].isArray() && !root["content"].empty()) {
if (root["content"][0]["type"].asString() == "text") {
message.content = ParseContents(std::move(root["content"])).value();
} else {
// deprecated, for supporting jan and should be removed in the future
// check if annotations is empty
if (!root["content"][0]["text"]["annotations"].empty()) {
// parse attachment
Json::Value attachments_json_array{Json::arrayValue};
Json::Value attachment;
attachment["file_id"] = ExtractFileId(
root["content"][0]["text"]["annotations"][0].asString());

Json::Value tools_json_array{Json::arrayValue};
Json::Value tool;
tool["type"] = "file_search";
tools_json_array.append(tool);

attachment["tools"] = tools_json_array;
attachment["file_id"] = attachments_json_array.append(attachment);

message.attachments =
ParseAttachments(std::move(attachments_json_array)).value();

message.attach_filename =
root["content"][0]["text"]["name"].asString();
message.size = root["content"][0]["text"]["size"].asUInt64();
message.rel_path =
root["content"][0]["text"]["annotations"][0].asString();
}

// parse content
Json::Value contents_json_array{Json::arrayValue};
Json::Value content;
Json::Value content_text;
Json::Value empty_annotations{Json::arrayValue};
content["type"] = "text";
content_text["value"] = root["content"][0]["text"]["value"];
content_text["annotations"] = empty_annotations;
content["text"] = content_text;
contents_json_array.append(content);
message.content =
ParseContents(std::move(contents_json_array)).value();
}
}
}

return message;
} catch (const std::exception& e) {
return cpp::fail(std::string("FromJsonString failed: ") + e.what());
Expand Down
29 changes: 29 additions & 0 deletions engine/common/repository/file_repository.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

#include "common/file.h"
#include "utils/result.hpp"

class FileRepository {
public:
virtual cpp::result<void, std::string> StoreFile(OpenAi::File& file_metadata,
const char* content,
uint64_t length) = 0;

virtual cpp::result<std::vector<OpenAi::File>, std::string> ListFiles(
const std::string& purpose, uint8_t limit, const std::string& order,
const std::string& after) const = 0;

virtual cpp::result<OpenAi::File, std::string> RetrieveFile(
const std::string file_id) const = 0;

virtual cpp::result<std::pair<std::unique_ptr<char[]>, size_t>, std::string>
RetrieveFileContent(const std::string& file_id) const = 0;

virtual cpp::result<std::pair<std::unique_ptr<char[]>, size_t>, std::string>
RetrieveFileContentByPath(const std::string& path) const = 0;

virtual cpp::result<void, std::string> DeleteFileLocal(
const std::string& file_id) = 0;

virtual ~FileRepository() = default;
};
Loading