1919
2020namespace OpenAi {
2121
22+ inline std::string ExtractFileId (const std::string& path) {
23+ // Handle both forward and backward slashes
24+ auto last_slash = path.find_last_of (" /\\ " );
25+ if (last_slash == std::string::npos)
26+ return " " ;
27+
28+ auto filename = path.substr (last_slash + 1 );
29+ auto dot_pos = filename.find (' .' );
30+ if (dot_pos == std::string::npos)
31+ return " " ;
32+
33+ return filename.substr (0 , dot_pos);
34+ }
35+
2236// Represents a message within a thread.
2337struct Message : JsonSerializable {
2438 Message () = default ;
@@ -70,6 +84,12 @@ struct Message : JsonSerializable {
7084 // 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.
7185 Cortex::VariantMap metadata;
7286
87+ // deprecated. remove in the future
88+ std::optional<std::string> attach_filename;
89+ std::optional<uint64_t > size;
90+ std::optional<std::string> rel_path;
91+ // end deprecated
92+
7393 static cpp::result<Message, std::string> FromJsonString (
7494 std::string&& json_str) {
7595 Json::Value root;
@@ -98,7 +118,6 @@ struct Message : JsonSerializable {
98118 message.completed_at = root[" completed_at" ].asUInt ();
99119 message.incomplete_at = root[" incomplete_at" ].asUInt ();
100120 message.role = RoleFromString (std::move (root[" role" ].asString ()));
101- message.content = ParseContents (std::move (root[" content" ])).value ();
102121
103122 message.assistant_id = std::move (root[" assistant_id" ].asString ());
104123 message.run_id = std::move (root[" run_id" ].asString ());
@@ -114,6 +133,54 @@ struct Message : JsonSerializable {
114133 }
115134 }
116135
136+ if (root.isMember (" content" )) {
137+ if (root[" content" ].isArray () && !root[" content" ].empty ()) {
138+ if (root[" content" ][0 ][" type" ].asString () == " text" ) {
139+ message.content = ParseContents (std::move (root[" content" ])).value ();
140+ } else {
141+ // deprecated, for supporting jan and should be removed in the future
142+ // check if annotations is empty
143+ if (!root[" content" ][0 ][" text" ][" annotations" ].empty ()) {
144+ // parse attachment
145+ Json::Value attachments_json_array{Json::arrayValue};
146+ Json::Value attachment;
147+ attachment[" file_id" ] = ExtractFileId (
148+ root[" content" ][0 ][" text" ][" annotations" ][0 ].asString ());
149+
150+ Json::Value tools_json_array{Json::arrayValue};
151+ Json::Value tool;
152+ tool[" type" ] = " file_search" ;
153+ tools_json_array.append (tool);
154+
155+ attachment[" tools" ] = tools_json_array;
156+ attachment[" file_id" ] = attachments_json_array.append (attachment);
157+
158+ message.attachments =
159+ ParseAttachments (std::move (attachments_json_array)).value ();
160+
161+ message.attach_filename =
162+ root[" content" ][0 ][" text" ][" name" ].asString ();
163+ message.size = root[" content" ][0 ][" text" ][" size" ].asUInt64 ();
164+ message.rel_path =
165+ root[" content" ][0 ][" text" ][" annotations" ][0 ].asString ();
166+ }
167+
168+ // parse content
169+ Json::Value contents_json_array{Json::arrayValue};
170+ Json::Value content;
171+ Json::Value content_text;
172+ Json::Value empty_annotations{Json::arrayValue};
173+ content[" type" ] = " text" ;
174+ content_text[" value" ] = root[" content" ][0 ][" text" ][" value" ];
175+ content_text[" annotations" ] = empty_annotations;
176+ content[" text" ] = content_text;
177+ contents_json_array.append (content);
178+ message.content =
179+ ParseContents (std::move (contents_json_array)).value ();
180+ }
181+ }
182+ }
183+
117184 return message;
118185 } catch (const std::exception& e) {
119186 return cpp::fail (std::string (" FromJsonString failed: " ) + e.what ());
0 commit comments