diff --git a/CMakeLists.txt b/CMakeLists.txt index 52bd513..b10b649 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,6 +101,7 @@ set(SOURCES src/utils.cpp src/prompts.cpp src/config.cpp + src/core/metadata.cpp ) # Get PostgreSQL version to handle platform-specific naming conventions diff --git a/src/core/metadata.cpp b/src/core/metadata.cpp new file mode 100644 index 0000000..cb38fb6 --- /dev/null +++ b/src/core/metadata.cpp @@ -0,0 +1,42 @@ +#include "metadata.hpp" + +using json = nlohmann::json; + +json extractSources(const std::string& text) { + json sources = json::array(); + + if (text.find("ST_") != std::string::npos) { + sources.push_back({ + {"title", "PostGIS Documentation"}, + {"url", "https://postgis.net/docs/"}}); + } + + if (text.find("SELECT") != std::string::npos) { + sources.push_back({ + {"title", "PostgreSQL SELECT"}, + {"url", "https://www.postgresql.org/docs/current/sql-select.html"}}); + } + + return sources; +} + +double calculateConfidence(const std::string& text) { + if (text.length() > 150) return 0.9; + if (text.length() > 50) return 0.75; + return 0.6; +} + +json extractTags(const std::string& text) { + json tags = json::array(); + + if (text.find("ST_") != std::string::npos) + tags.push_back("postgis"); + + if (text.find("JOIN") != std::string::npos) + tags.push_back("join"); + + if (text.find("INDEX") != std::string::npos) + tags.push_back("performance"); + + return tags; +} \ No newline at end of file diff --git a/src/core/metadata.hpp b/src/core/metadata.hpp new file mode 100644 index 0000000..0f5eb89 --- /dev/null +++ b/src/core/metadata.hpp @@ -0,0 +1,7 @@ +#pragma once +#include +#include + +nlohmann::json extractSources(const std::string& text); +double calculateConfidence(const std::string& text); +nlohmann::json extractTags(const std::string& text); \ No newline at end of file diff --git a/src/core/response_formatter.cpp b/src/core/response_formatter.cpp index cdf6e3a..fc2dc22 100644 --- a/src/core/response_formatter.cpp +++ b/src/core/response_formatter.cpp @@ -3,6 +3,7 @@ #include #include #include +#include "metadata.hpp" namespace pg_ai { namespace { @@ -72,6 +73,13 @@ std::string ResponseFormatter::createJSONResponse( response["row_limit_applied"] = true; } + // ✅ Add AI metadata (only if explanation exists) +if (!result.explanation.empty()) { + response["sources"] = extractSources(result.explanation); + response["confidence"] = calculateConfidence(result.explanation); + response["tags"] = extractTags(result.explanation); +} + return response.dump(2); // Pretty print with 2-space indentation } diff --git a/tests/unit/test_metadata.cpp b/tests/unit/test_metadata.cpp new file mode 100644 index 0000000..f0d6733 --- /dev/null +++ b/tests/unit/test_metadata.cpp @@ -0,0 +1,17 @@ +#include +#include "/home/lucifer/Desktop/pg_ai_query/src/core/metadata.hpp" + +int main() { + std::string text = "Use ST_Distance in PostGIS"; + + auto sources = extractSources(text); + assert(!sources.empty()); + + double conf = calculateConfidence(text); + assert(conf > 0); + + auto tags = extractTags(text); + assert(!tags.empty()); + + return 0; +} \ No newline at end of file diff --git a/tests/unit/test_response_formatter.cpp b/tests/unit/test_response_formatter.cpp index 3735e00..853c717 100644 --- a/tests/unit/test_response_formatter.cpp +++ b/tests/unit/test_response_formatter.cpp @@ -342,3 +342,52 @@ TEST_F(ResponseFormatterTest, JSONIsPrettyPrinted) { // Pretty-printed JSON should contain newlines EXPECT_THAT(output, testing::HasSubstr("\n")); } + +// Test that documentation links appear in formatted response + +TEST_F(ResponseFormatterTest, IncludesPostgresDocumentationLink) { + QueryResult result = createBasicResult(); + + result.explanation = + "PostgreSQL indexes improve query performance. " + "See https://www.postgresql.org/docs/current/indexes.html"; + + Configuration config = createConfig(false, true, false, false); + + std::string formatted = + pg_ai::ResponseFormatter::formatResponse(result, config); + + EXPECT_NE(formatted.find("postgresql.org/docs"), std::string::npos); +} + +// Test specific documentation page +TEST_F(ResponseFormatterTest, IndexDocumentationLinkPresent) { + QueryResult result = createBasicResult(); + + result.explanation = + "Documentation: https://www.postgresql.org/docs/current/indexes.html"; + + Configuration config = createConfig(false, true, false, false); + + std::string formatted = + pg_ai::ResponseFormatter::formatResponse(result, config); + + EXPECT_NE(formatted.find("indexes.html"), std::string::npos); +} + // Test when no documentation link exists +TEST_F(ResponseFormatterTest, HandlesMissingDocumentationLink) { + QueryResult result = createBasicResult(); + + result.explanation = "PostgreSQL indexes improve performance."; + + Configuration config = createConfig(false, true, false, false); + + std::string formatted = + pg_ai::ResponseFormatter::formatResponse(result, config); + + EXPECT_EQ(formatted.find("postgresql.org/docs"), std::string::npos); +} + + + +