diff --git a/src/mcp/HandlersMemory.hpp b/src/mcp/HandlersMemory.hpp index a56fa12..ea45e9b 100644 --- a/src/mcp/HandlersMemory.hpp +++ b/src/mcp/HandlersMemory.hpp @@ -1,10 +1,12 @@ #pragma once #include +#include #include #include #include #include +#include #include #include #include @@ -190,11 +192,13 @@ inline std::optional extract_int_field(const std::string& json, const std:: std::size_t start = pos; while (pos < json.size() && (std::isdigit(static_cast(json[pos])) || json[pos] == '-')) ++pos; if (start == pos) return std::nullopt; - try { - return std::stoi(json.substr(start, pos - start)); - } catch (...) { + const std::string_view token{json.data() + start, pos - start}; + int value = 0; + const auto parseResult = std::from_chars(token.data(), token.data() + token.size(), value); + if (parseResult.ec != std::errc() || parseResult.ptr != token.data() + token.size()) { return std::nullopt; } + return value; } inline std::string iso8601_from_tp(std::chrono::system_clock::time_point tp) { @@ -299,10 +303,12 @@ inline std::vector parse_float_array(const std::string& json, const std:: if (pos >= arr.size()) break; std::size_t end = pos; while (end < arr.size() && (std::isdigit(static_cast(arr[end])) || arr[end] == '.' || arr[end] == 'e' || arr[end] == 'E' || arr[end] == '+' || arr[end] == '-')) ++end; - try { - values.push_back(std::stof(arr.substr(pos, end - pos))); - } catch (...) { - // Skip unparsable token. + float parsed = 0.0f; + const char* begin = arr.c_str() + pos; + const char* finish = arr.c_str() + end; + const auto fc = std::from_chars(begin, finish, parsed); + if (fc.ec == std::errc() && fc.ptr == finish) { + values.push_back(parsed); } pos = end; } @@ -384,7 +390,9 @@ inline std::string upsert_memory(const std::string& reqJson) { std::vector ids; ids.reserve(items.size()); +#if defined(__cpp_exceptions) try { +#endif for (auto& parsed : items) { kom::ItemRow row; row.id = parsed.id; @@ -412,11 +420,14 @@ inline std::string upsert_memory(const std::string& reqJson) { dal.upsertEmbeddings(std::vector{emb}); } } - if (hasTx) dal.commit(); +#if defined(__cpp_exceptions) } catch (const std::exception& ex) { if (hasTx) dal.rollback(); return detail::error_response("internal_error", ex.what()); } +#endif + + if (hasTx) dal.commit(); std::ostringstream os; os << "{\"upserted\":" << ids.size(); @@ -530,23 +541,33 @@ inline std::string save_context(const std::string& reqJson) { } } + std::string insertedId; +#if defined(__cpp_exceptions) try { - const std::string id = dal.upsertItem(row); - auto stored = dal.getItemById(id); - const auto createdTp = stored ? stored->created_at : row.created_at; - std::string createdIso = detail::iso8601_from_tp(createdTp); - if (createdIso.empty()) { - createdIso = detail::iso8601_from_tp(std::chrono::system_clock::now()); - } - - std::ostringstream os; - os << "{\"id\":\"" << detail::json_escape(id) << "\""; - os << ",\"created_at\":\"" << createdIso << "\""; - os << "}"; - return os.str(); +#endif + insertedId = dal.upsertItem(row); +#if defined(__cpp_exceptions) } catch (const std::exception& ex) { return detail::error_response("internal_error", ex.what()); } +#endif + + if (insertedId.empty()) { + return detail::error_response("internal_error", "failed to upsert item"); + } + + auto stored = dal.getItemById(insertedId); + const auto createdTp = stored ? stored->created_at : row.created_at; + std::string createdIso = detail::iso8601_from_tp(createdTp); + if (createdIso.empty()) { + createdIso = detail::iso8601_from_tp(std::chrono::system_clock::now()); + } + + std::ostringstream os; + os << "{\"id\":\"" << detail::json_escape(insertedId) << "\""; + os << ",\"created_at\":\"" << createdIso << "\""; + os << "}"; + return os.str(); } inline std::string recall_context(const std::string& reqJson) {