Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
119 commits
Select commit Hold shift + click to select a range
7e9c218
Refactor user ID type from int to int64 and add new agent endpoint fo…
rag-nar1 Jun 26, 2025
dd317b2
Update go.mod to require AI-Agent v1.0.2 and add response.md to .giti…
rag-nar1 Jun 26, 2025
b29c710
feat: refactor project and table handling, update deployment flag and…
rag-nar1 Jun 27, 2025
1ac671b
refactor: the returned data from the get all tables handler
rag-nar1 Jun 27, 2025
68a7251
feat: add schema property to tables and update documentation
rag-nar1 Jun 27, 2025
c58604b
refactor: update user ID type to int64 across multiple files and enha…
rag-nar1 Jun 28, 2025
f2df990
refactor: update table schema references and enhance JSON struct tags…
rag-nar1 Jun 28, 2025
985b6db
refactor: update table handling to use new Table struct and enhance D…
rag-nar1 Jun 28, 2025
b766c8f
feat: added the DDL statement gnerator fot diff between two tables
rag-nar1 Jun 29, 2025
a458abb
feat: add UpdateTableSchema struct and RenameRelation type for schema…
rag-nar1 Jun 29, 2025
9200183
remove playground directory
rag-nar1 Jun 29, 2025
742b5c5
feat: implement table schema synchronization and enhance ownership ch…
rag-nar1 Jun 29, 2025
5538ecc
refactor: remove old body comments and update to new Table struct
rag-nar1 Jun 29, 2025
8e25ae1
first version for the chatbot (not working)
OmarAlaraby Jun 29, 2025
9f9fc9f
feat: enhance ownership checks and add CheckOTableExist middleware fo…
rag-nar1 Jun 30, 2025
b311f19
feat: add GetTableSchemaHandler and update table schema handling in m…
rag-nar1 Jun 30, 2025
556e743
fix: correct GetAllTablesHanlder typo and add GetTableSchemaHandler d…
rag-nar1 Jun 30, 2025
56af17c
Merge branch 'deploy' into refactor-tables
rag-nar1 Jun 30, 2025
e9c7867
Add AgentAccept handler and update routes for agent acceptance
rag-nar1 Jun 30, 2025
18e57cc
Merge pull request #40 from Database-Hosting-Services/refactor-tables
rag-nar1 Jun 30, 2025
d052f3b
Update Swagger documentation and Go module dependencies
rag-nar1 Jun 30, 2025
63d3278
feat: enable deployment mode and update table schema documentation in…
rag-nar1 Jun 30, 2025
9ee6be9
Merge pull request #41 from Database-Hosting-Services/refactor-tables
rag-nar1 Jun 30, 2025
45da124
Init sqlEditor package
GergesHany Jul 1, 2025
943ad7a
feat: implement SQL Editor module with query execution capabilities
GergesHany Jul 1, 2025
6bd5e34
Documentation Updates
GergesHany Jul 3, 2025
cfa953e
feat(SqlEditor): Add comprehensive SQL query validation and Swagger d…
GergesHany Jul 3, 2025
98c8958
fix: disable deployment mode and simplify filter check in repository
rag-nar1 Jul 3, 2025
bb5255f
chatbot base functionality
OmarAlaraby Jul 3, 2025
f3b3561
Merge branch 'AI' into chatbot
OmarAlaraby Jul 3, 2025
985452b
Update AI/models.go
OmarAlaraby Jul 3, 2025
3240885
Merge pull request #42 from Database-Hosting-Services/chatbot
OmarAlaraby Jul 3, 2025
1bdb9ac
fix duplicated imports
OmarAlaraby Jul 3, 2025
6032073
document chatbot endpoint
OmarAlaraby Jul 3, 2025
76a96a5
fix: update CheckOwnershipQueryTable to use project ID instead of pro…
rag-nar1 Jul 4, 2025
24ff1c4
Merge branch 'AI' of github.com:Database-Hosting-Services/API into AI
rag-nar1 Jul 4, 2025
f60b672
Merge branch 'refactor-tables' into AI
rag-nar1 Jul 4, 2025
6234d7a
feat: implement agent functionality and request handling in AI module
rag-nar1 Jul 4, 2025
aa80d7a
Merge branch 'logging' into AI
rag-nar1 Jul 4, 2025
fdc0397
fix: improve logging for AI report generation and agent query execution
rag-nar1 Jul 4, 2025
dd147ce
Merge branch 'deploy' into AI
rag-nar1 Jul 4, 2025
20280b7
feat: add AI agent query endpoints and logging functionality
rag-nar1 Jul 4, 2025
ef74f8f
Merge branch 'AI' of github.com:Database-Hosting-Services/API into AI
rag-nar1 Jul 4, 2025
55a1edc
Merge pull request #43 from Database-Hosting-Services/AI
rag-nar1 Jul 4, 2025
7252312
fix: update deployment flag for production environment
rag-nar1 Jul 4, 2025
32c6528
Merge pull request #44 from Database-Hosting-Services/AI
rag-nar1 Jul 4, 2025
9fe9dc5
feat: add AI agent query endpoints and update error response handling
rag-nar1 Jul 4, 2025
ae14caf
Merge pull request #45 from Database-Hosting-Services/AI
rag-nar1 Jul 4, 2025
8f5ef49
fix: ensure data is an empty slice if no tables are found
rag-nar1 Jul 8, 2025
c9a50c9
feat: add project and table existence checks in middleware
rag-nar1 Jul 8, 2025
0f543b8
Refactor response handling to include request context in error and su…
rag-nar1 Jul 8, 2025
187893e
Merge pull request #46 from Database-Hosting-Services/logging
rag-nar1 Jul 8, 2025
43d4069
fix: update ResponseHandler to include request context in error respo…
rag-nar1 Jul 8, 2025
0247090
Merge pull request #47 from Database-Hosting-Services/logging
rag-nar1 Jul 8, 2025
fa802de
fix: include request URI in response logging for better traceability
rag-nar1 Jul 8, 2025
37102e2
fix: update response logging to store response object directly
rag-nar1 Jul 8, 2025
0dc983c
Merge pull request #48 from Database-Hosting-Services/logging
rag-nar1 Jul 8, 2025
331eb7d
fix: include request header and body in event logging for better trac…
rag-nar1 Jul 8, 2025
5b8a9bf
fix: add ownership check middleware to project routes for enhanced se…
rag-nar1 Jul 8, 2025
ea6edff
fix: refactor project routes to separate ownership check middleware f…
rag-nar1 Jul 8, 2025
583f487
fix: ensure error level is logged in CreateResponse function for bett…
rag-nar1 Jul 9, 2025
7f02180
fix: refactor GetUser function to use pgxscan for improved database q…
rag-nar1 Jul 9, 2025
ddd8e8d
fix: update CreateResponse to log request body as structured data for…
rag-nar1 Jul 9, 2025
8145a66
fix: update JsonString function to use 'any' type for improved type f…
rag-nar1 Jul 9, 2025
e963144
fix: update database connection configuration to set default query ex…
rag-nar1 Jul 9, 2025
86848df
refactor(config): remove unused prepared statement cleanup code
GergesHany Jul 9, 2025
7acba33
refactor(config): remove unused HTTP error helper functions
GergesHany Jul 9, 2025
335a61d
refactor(sqleditor): remove empty SqlQueries.go file
GergesHany Jul 9, 2025
4eda04e
fix(schema): update GetTableConstraints to set ColumnName for CHECK c…
rag-nar1 Jul 9, 2025
83a6c8c
fix(schema): update GetTableConstraints to handle NOT NULL constraints
rag-nar1 Jul 10, 2025
078054e
feat(validation): add non-negative number check for pagination parame…
rag-nar1 Jul 10, 2025
c5896aa
fix(handlers): enhance error handling in SignIn function to include s…
rag-nar1 Jul 10, 2025
e029e7e
fix(repository): add logging for query execution in ReadTableData fun…
rag-nar1 Jul 10, 2025
c7055d2
fix(response): add HTTP method to event logging in CreateResponse fun…
rag-nar1 Jul 10, 2025
2f9844d
feat(tables): implement InsertRowHandler and InserNewRow service func…
rag-nar1 Jul 10, 2025
42d9c0d
Merge pull request #49 from Database-Hosting-Services/insert-rows
rag-nar1 Jul 10, 2025
eae4fc9
fix(config): update deploy flag to true for production environment
rag-nar1 Jul 10, 2025
46d0be9
feat(tables): add InsertRowHandler and RowValue struct for inserting …
rag-nar1 Jul 10, 2025
76090d0
fix(handlers): correct parameter type in ReadTableHandler documentation
rag-nar1 Jul 10, 2025
5ae8ffd
fix(handlers): update parameter name in ReadTableHandler documentation
rag-nar1 Jul 10, 2025
1200acb
fix(config): set deploy flag to false for development environment
rag-nar1 Jul 10, 2025
50f625a
fix(config): update deploy flag to true for production environment
rag-nar1 Jul 10, 2025
73706a9
fix(response): update JsonString function to return string instead of…
rag-nar1 Jul 10, 2025
e0aa854
fix(response): simplify JsonString function to return raw string from…
rag-nar1 Jul 10, 2025
bc1bea2
fix(dependencies): update AI-Agent to version 1.0.7
rag-nar1 Jul 10, 2025
3a4d646
refactor(models): remove redundant fields from AgentResponse and adju…
rag-nar1 Jul 10, 2025
47eb879
fix: ai agent json response format
rag-nar1 Jul 10, 2025
f689377
Update The /api/projects/{project_id}/sqlEditor/run-query endpoint me…
GergesHany Jul 11, 2025
01bc90c
Documentation Updates
GergesHany Jul 11, 2025
9c585bf
refactor(schemas): remove unused getDatabaseByName function
GergesHany Jul 11, 2025
95d73e6
refactor(schemas): remove empty services.go file
GergesHany Jul 11, 2025
292eb86
Remove CloseAllPools comment because this method has changed
GergesHany Jul 11, 2025
c2c8db3
feat(SqlEditor); Add proper error handling for syntax and permission …
GergesHany Jul 11, 2025
2354750
Documentation Updates
GergesHany Jul 11, 2025
c32a548
update the response logging to include the request body
rag-nar1 Jul 11, 2025
4ba6544
update the response logging to include the request body
rag-nar1 Jul 11, 2025
e6e2c8e
change refernces
rag-nar1 Jul 11, 2025
f03fe1d
filters
rag-nar1 Jul 11, 2025
682843f
Handle There is no data case
GergesHany Jul 12, 2025
b9adb23
update agent
rag-nar1 Jul 12, 2025
901622b
table names fixed
rag-nar1 Jul 12, 2025
8cfe837
extracting rows from asn empty table returns an empty list
rag-nar1 Jul 12, 2025
faf725f
added body to the logs for the create table endpoint
rag-nar1 Jul 12, 2025
b29dc95
costs are up
rag-nar1 Jul 12, 2025
1f09947
negatice cost ha
rag-nar1 Jul 12, 2025
0591341
costs
rag-nar1 Jul 12, 2025
74487b0
cost back
rag-nar1 Jul 12, 2025
9af3dd7
tanle name resolved
rag-nar1 Jul 12, 2025
7f7e73c
added body to the logs for the insert row in
rag-nar1 Jul 12, 2025
7b09ae5
solve inserting new row
rag-nar1 Jul 12, 2025
a6b5a97
Refactor CORS middleware to allow all origins and common HTTP methods…
rag-nar1 Jul 12, 2025
f1cb6c4
Add function to remove JSON code segments from responses in AgentQuery
rag-nar1 Jul 12, 2025
3d152ad
error
rag-nar1 Jul 12, 2025
ede8bb5
Update SQL queries in SqlQueries.go to use COALESCE for better handli…
rag-nar1 Jul 12, 2025
af1a606
Add dummy data to analytics handlers
rag-nar1 Jul 13, 2025
35284e3
Update storage dummy data in analytics models to use kilobytes for ma…
rag-nar1 Jul 13, 2025
87457f9
Refactor dummy data in analytics models to use smaller values for sto…
rag-nar1 Jul 13, 2025
165c84e
Merge branch 'main' into deploy
rag-nar1 Jul 13, 2025
f88582a
Update handlers.go
rag-nar1 Jul 13, 2025
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
3 changes: 2 additions & 1 deletion .air.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ delay = 1000 # 1 second delay after changes
include_ext = ["go"]
include_dir = ["main", "accounts", "build", "caching", "config",
"middleware", "projects", "response", "scripts",
"utils", "test", "indexes", "AI", "analytics"]
"utils", "test", "indexes", "AI", "analytics",
"tables", "SqlEditor"]
exclude_dir = ["tmp", "vendor", "testdata", ".git"]

kill_delay = "1s"
Expand Down
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ build/*
*.env
.idea
.vscode
playground
playground/*
tmp/main*
*.log
curl.sh
.qodo
*.log
pr.md
response.md
response.*
/tmp
insert_students.sh
4 changes: 2 additions & 2 deletions AI/db_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package ai_test

import (
ai "DBHS/AI"
"DBHS/utils"
"context"
"fmt"
"log"
Expand Down Expand Up @@ -44,7 +44,7 @@ func TestExtractDatabaseSchema(t *testing.T) {
})

// extract schema
schema, err := ai.ExtractDatabaseSchema(context.Background(), db)
schema, err := utils.ExtractDatabaseSchema(context.Background(), db)
if err != nil {
t.Fatalf("Failed to extract database schema: %v", err)
}
Expand Down
283 changes: 276 additions & 7 deletions AI/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,28 @@ package ai
import (
"DBHS/config"
"DBHS/response"
"net/http"
"encoding/json"
"time"

"github.com/axiomhq/axiom-go/axiom"
"github.com/axiomhq/axiom-go/axiom/ingest"
"github.com/gorilla/mux"
"io"
"net/http"
)

func getAnalytics() Analytics { // this only a placeholder for now
return Analytics{}
}


// @Summary Generate AI Report
// @Description Generate an AI-powered analytics report for a specific project
// @Tags AI
// @Accept json
// @Produce json
// @Param project_id path string true "Project ID"
// @Success 200 {object} response.Response{data=object} "Report generated successfully"
// @Failure 500 {object} response.Response "Internal server error"
// @Failure 500 {object} response.ErrorResponse500 "Internal server error"
// @Router /projects/{project_id}/ai/report [get]
// @Security BearerAuth
func Report(app *config.Application) http.HandlerFunc {
Expand All @@ -29,17 +34,281 @@ func Report(app *config.Application) http.HandlerFunc {
projectID := vars["project_id"]

// get user id from context
userID := r.Context().Value("user-id").(int)
userID := r.Context().Value("user-id").(int64)

Analytics := getAnalytics() // TODO: get real analytics
AI := config.AI

report, err := getReport(projectID, userID, Analytics, AI)
if err != nil {
response.InternalServerError(w, err.Error(), err)
response.InternalServerError(w, r, err.Error(), err)
config.AxiomLogger.IngestEvents(r.Context(), "ai-logs", []axiom.Event{
{
ingest.TimestampField: time.Now(),
"project_id": projectID,
"user_id": userID,
"error": err.Error(),
"message": "Failed to generate AI report",
},
})
return
}

config.AxiomLogger.IngestEvents(r.Context(), "ai-logs", []axiom.Event{
{
ingest.TimestampField: time.Now(),
"project_id": projectID,
"user_id": userID,
"report": report,
"status": "success",
"message": "AI report generated successfully",
},
})

response.OK(w, r, "Report generated successfully", report)
}
}

// ChatBotAsk godoc
// @Summary Chat Bot Ask
// @Description This endpoint allows users to ask questions to the chatbot, which will respond using AI. It also saves the chat history for future reference.
// @Tags AI
// @Accept json
// @Produce json
// @Param project_id path string true "Project ID"
// @Param ChatBotRequest body ChatBotRequest true "Chat Bot Request"
// @Success 200 {object} response.Response{data=object} "Answer generated successfully"
// @Failure 500 {object} response.ErrorResponse500 "Internal server error"
// @Router /projects/{project_id}/ai/chatbot/ask [post]
// @Security BearerAuth
func ChatBotAsk(app *config.Application) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {

vars := mux.Vars(r)
projectOID := vars["project_id"]
projectID, err := GetProjectIDfromOID(r.Context(), config.DB, projectOID)
if err != nil {
response.InternalServerError(w, r, "Failed to get project ID", err)
return
}
userID64 := r.Context().Value("user-id").(int64)
userID := int(userID64)

var userRequest ChatBotRequest
if err := json.NewDecoder(r.Body).Decode(&userRequest); err != nil {
response.BadRequest(w, r, "Invalid request body", err)
return
}

transaction, err := config.DB.Begin(r.Context())
if err != nil {
app.ErrorLog.Println(err.Error())
response.InternalServerError(w, r, "Failed to start database transaction", err)
return
}

// i should ignore this step if the client passed the chat history with the request
chat_data, err := GetOrCreateChatData(r.Context(), transaction, userID, projectID)
if err != nil {
app.ErrorLog.Println(err.Error())
response.InternalServerError(w, r, "Failed to get or create chat data", err)
return
}
app.InfoLog.Printf("Chat data: %+v", chat_data)

answer, err := config.AI.QueryChat(userRequest.Question)
if err != nil {
response.InternalServerError(w, r, err.Error(), err)
return
}

err = SaveChatAction(r.Context(), transaction, chat_data.ID, userID, userRequest.Question, answer.ResponseText)
if err != nil {
response.InternalServerError(w, r, err.Error(), err)
return
}

if err := transaction.Commit(r.Context()); err != nil {
app.ErrorLog.Println(err.Error())
response.InternalServerError(w, r, "Failed to commit database transaction", err)
return
}

response.OK(w, r, "Answer generated successfully", answer)
}
}

// Agent godoc
// @Summary AI Agent Query
// @Description This endpoint allows users to query the AI agent with a prompt. The agent will respond with a schema change suggestion based on the prompt.
// @Tags AI
// @Accept json
// @Produce json
// @Param project_id path string true "Project ID"
// @Param Request body Request true "Request"
// @Success 200 {object} response.Response{data=AgentResponse} "Agent query successful"
// @Failure 400 {object} response.ErrorResponse400 "Bad request"
// @Failure 500 {object} response.ErrorResponse500 "Internal server error"
// @Router /projects/{project_id}/ai/agent [post]
// @Security JWTAuth
func Agent(app *config.Application) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// get the request body
body, err := io.ReadAll(r.Body)
if err != nil {
response.BadRequest(w, r, "Failed to read request body", err)
return
}

response.OK(w, "Report generated successfully", report)
// parse the request body
request := &Request{}
err = json.Unmarshal(body, request)
if err != nil {
response.BadRequest(w, r, "Failed to parse request body", err)
return
}
// check if the request body is valid
if request.Prompt == "" {
response.BadRequest(w, r, "Prompt is required", nil)
return
}

// get project id from path
vars := mux.Vars(r)
projectUID := vars["project_id"]

// get user id from context
userID := r.Context().Value("user-id").(int64)

AIresponse, err := AgentQuery(projectUID, userID, request.Prompt, config.AI)
if err != nil {
response.InternalServerError(w, r, "error while querying agent", err)
// log the error to Axiom
config.AxiomLogger.IngestEvents(r.Context(), "ai-logs", []axiom.Event{
{
ingest.TimestampField: time.Now(),
"project_id": projectUID,
"user_id": userID,
"error": err.Error(),
"message": "Failed to query agent",
},
})
return
}
// log the success to Axiom
config.AxiomLogger.IngestEvents(r.Context(), "ai-logs", []axiom.Event{
{
ingest.TimestampField: time.Now(),
"project_id": projectUID,
"user_id": userID,
"message": "Agent query successful",
"ddl": AIresponse.SchemaDDL,
"prompt": request.Prompt,
"SchemaChanges": AIresponse.SchemaChanges,
"response": AIresponse.Response,
},
})

response.OK(w, r, "Agent query successful", AIresponse)
}
}
}

// AgentAccept godoc
// @Summary Accept AI Agent Query
// @Description This endpoint allows users to accept the AI agent's query and execute the schema changes
// @Tags AI
// @Produce json
// @Param project_id path string true "Project ID"
// @Success 200 {object} response.Response "Query executed successfully"
// @Failure 400 {object} response.ErrorResponse400 "Bad request"
// @Failure 500 {object} response.ErrorResponse500 "Internal server error"
// @Router /projects/{project_id}/ai/agent/accept [post]
// @Security JWTAuth
func AgentAccept(app *config.Application) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// get project id from path
vars := mux.Vars(r)
projectUID := vars["project_id"]
// get user id from context
userID := r.Context().Value("user-id").(int64)

// execute the agent query
err := AgentExec(projectUID, userID, config.AI)
if err != nil {
if err.Error() == "changes expired or not found" {
response.BadRequest(w, r, "No schema changes found or changes expired", nil)
} else {
response.InternalServerError(w, r, "error while executing agent", err)
}
// log the error to Axiom
config.AxiomLogger.IngestEvents(r.Context(), "ai-logs", []axiom.Event{
{
ingest.TimestampField: time.Now(),
"project_id": projectUID,
"user_id": userID,
"error": err.Error(),
"message": "Failed to execute agent query",
},
})
return
}
// log the success to Axiom
config.AxiomLogger.IngestEvents(r.Context(), "ai-logs", []axiom.Event{
{
ingest.TimestampField: time.Now(),
"project_id": projectUID,
"user_id": userID,
"message": "Agent query executed successfully",
},
})
response.OK(w, r, "query executed successfully", nil)
}
}

// AgentCancel godoc
// @Summary Cancel AI Agent Query
// @Description This endpoint allows users to cancel an AI agent query
// @Tags AI
// @Produce json
// @Param project_id path string true "Project ID"
// @Success 200 {object} response.Response "Agent query cancelled successfully"
// @Failure 400 {object} response.ErrorResponse400 "Bad request"
// @Failure 500 {object} response.ErrorResponse500 "Internal server error"
// @Router /projects/{project_id}/ai/agent/cancel [post]
// @Security JWTAuth
func AgentCancel(app *config.Application) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// get project id from path
vars := mux.Vars(r)
projectUID := vars["project_id"]
// get user id from context
userID := r.Context().Value("user-id").(int64)
// cancel the agent query
err := ClearCacheForProject(projectUID)
if err != nil {
response.InternalServerError(w, r, "error while cancelling agent query", err)
// log the error to Axiom
config.AxiomLogger.IngestEvents(r.Context(), "ai-logs", []axiom.Event{
{
ingest.TimestampField: time.Now(),
"project_id": projectUID,
"user_id": userID,
"error": err.Error(),
"message": "Failed to cancel agent query",
},
})
return
}
// log the cancellation to Axiom
config.AxiomLogger.IngestEvents(r.Context(), "ai-logs", []axiom.Event{
{
ingest.TimestampField: time.Now(),
"project_id": projectUID,
"user_id": userID,
"message": "Agent query cancelled",
},
})

response.OK(w, r, "Agent query cancelled successfully", nil)
}
}
Loading