feat: creating events and attaching locations
This commit is contained in:
18
backend/.gen/haystack/haystack/model/user_events.go
Normal file
18
backend/.gen/haystack/haystack/model/user_events.go
Normal file
@ -0,0 +1,18 @@
|
||||
//
|
||||
// Code generated by go-jet DO NOT EDIT.
|
||||
//
|
||||
// WARNING: Changes to this file may cause incorrect behavior
|
||||
// and will be lost if the code is regenerated
|
||||
//
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type UserEvents struct {
|
||||
ID uuid.UUID `sql:"primary_key"`
|
||||
EventID uuid.UUID
|
||||
UserID uuid.UUID
|
||||
}
|
@ -18,6 +18,7 @@ func UseSchema(schema string) {
|
||||
ImageTags = ImageTags.FromSchema(schema)
|
||||
ImageText = ImageText.FromSchema(schema)
|
||||
Locations = Locations.FromSchema(schema)
|
||||
UserEvents = UserEvents.FromSchema(schema)
|
||||
UserImages = UserImages.FromSchema(schema)
|
||||
UserImagesToProcess = UserImagesToProcess.FromSchema(schema)
|
||||
UserLocations = UserLocations.FromSchema(schema)
|
||||
|
81
backend/.gen/haystack/haystack/table/user_events.go
Normal file
81
backend/.gen/haystack/haystack/table/user_events.go
Normal file
@ -0,0 +1,81 @@
|
||||
//
|
||||
// Code generated by go-jet DO NOT EDIT.
|
||||
//
|
||||
// WARNING: Changes to this file may cause incorrect behavior
|
||||
// and will be lost if the code is regenerated
|
||||
//
|
||||
|
||||
package table
|
||||
|
||||
import (
|
||||
"github.com/go-jet/jet/v2/postgres"
|
||||
)
|
||||
|
||||
var UserEvents = newUserEventsTable("haystack", "user_events", "")
|
||||
|
||||
type userEventsTable struct {
|
||||
postgres.Table
|
||||
|
||||
// Columns
|
||||
ID postgres.ColumnString
|
||||
EventID postgres.ColumnString
|
||||
UserID postgres.ColumnString
|
||||
|
||||
AllColumns postgres.ColumnList
|
||||
MutableColumns postgres.ColumnList
|
||||
}
|
||||
|
||||
type UserEventsTable struct {
|
||||
userEventsTable
|
||||
|
||||
EXCLUDED userEventsTable
|
||||
}
|
||||
|
||||
// AS creates new UserEventsTable with assigned alias
|
||||
func (a UserEventsTable) AS(alias string) *UserEventsTable {
|
||||
return newUserEventsTable(a.SchemaName(), a.TableName(), alias)
|
||||
}
|
||||
|
||||
// Schema creates new UserEventsTable with assigned schema name
|
||||
func (a UserEventsTable) FromSchema(schemaName string) *UserEventsTable {
|
||||
return newUserEventsTable(schemaName, a.TableName(), a.Alias())
|
||||
}
|
||||
|
||||
// WithPrefix creates new UserEventsTable with assigned table prefix
|
||||
func (a UserEventsTable) WithPrefix(prefix string) *UserEventsTable {
|
||||
return newUserEventsTable(a.SchemaName(), prefix+a.TableName(), a.TableName())
|
||||
}
|
||||
|
||||
// WithSuffix creates new UserEventsTable with assigned table suffix
|
||||
func (a UserEventsTable) WithSuffix(suffix string) *UserEventsTable {
|
||||
return newUserEventsTable(a.SchemaName(), a.TableName()+suffix, a.TableName())
|
||||
}
|
||||
|
||||
func newUserEventsTable(schemaName, tableName, alias string) *UserEventsTable {
|
||||
return &UserEventsTable{
|
||||
userEventsTable: newUserEventsTableImpl(schemaName, tableName, alias),
|
||||
EXCLUDED: newUserEventsTableImpl("", "excluded", ""),
|
||||
}
|
||||
}
|
||||
|
||||
func newUserEventsTableImpl(schemaName, tableName, alias string) userEventsTable {
|
||||
var (
|
||||
IDColumn = postgres.StringColumn("id")
|
||||
EventIDColumn = postgres.StringColumn("event_id")
|
||||
UserIDColumn = postgres.StringColumn("user_id")
|
||||
allColumns = postgres.ColumnList{IDColumn, EventIDColumn, UserIDColumn}
|
||||
mutableColumns = postgres.ColumnList{EventIDColumn, UserIDColumn}
|
||||
)
|
||||
|
||||
return userEventsTable{
|
||||
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
|
||||
|
||||
//Columns
|
||||
ID: IDColumn,
|
||||
EventID: EventIDColumn,
|
||||
UserID: UserIDColumn,
|
||||
|
||||
AllColumns: allColumns,
|
||||
MutableColumns: mutableColumns,
|
||||
}
|
||||
}
|
@ -23,9 +23,12 @@ It is possible that there is no location or event on an image.
|
||||
|
||||
You should ask for a list of locations, as the user is likely to have this location saved. Reuse existing locations where possible.
|
||||
|
||||
Always reuse existing locations from listLocations. Do not create duplicates.
|
||||
|
||||
Do not create an event if you don't see any dates, or a name indicating an event.
|
||||
|
||||
Always reuse existing locations from listLocations . Do not create duplicates.
|
||||
Events can have an associated location, if you think there is a location, then you must either use a location from listLocations or you must create it first.
|
||||
Wherever possible, find the location in the image.
|
||||
`
|
||||
|
||||
// TODO: this should be read directly from a file on load.
|
||||
@ -64,23 +67,6 @@ const TOOLS = `
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "attachImageLocation",
|
||||
"description": "Add a location to an image. You must use UUID.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"locationId": {
|
||||
"type": "string",
|
||||
"description": "UUID of an existing location, you can use listLocations to get values, or use the return value of createLocation"
|
||||
}
|
||||
},
|
||||
"required": ["locationId"]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
@ -139,6 +125,12 @@ type AttachImageLocationArguments struct {
|
||||
LocationId string `json:"locationId"`
|
||||
}
|
||||
|
||||
type CreateEventArguments struct {
|
||||
Name string `json:"name"`
|
||||
Datetime string `json:"datetime"`
|
||||
LocationId string `json:"locationId"`
|
||||
}
|
||||
|
||||
func (agent EventLocationAgent) GetLocations(userId uuid.UUID, imageId uuid.UUID, imageName string, imageData []byte) error {
|
||||
var tools any
|
||||
err := json.Unmarshal([]byte(TOOLS), &tools)
|
||||
@ -299,6 +291,8 @@ func NewLocationEventAgent(locationModel models.LocationModel, eventModel models
|
||||
},
|
||||
}
|
||||
|
||||
// I'm not sure this one actually makes sense either.
|
||||
// I think the earlier tool can do more.
|
||||
toolHandler.Handlers["attachImageLocation"] = ToolHandler[AttachImageLocationArguments, model.ImageLocations]{
|
||||
FunctionName: "attachImageLocation",
|
||||
Parse: func(stringArgs string) (AttachImageLocationArguments, error) {
|
||||
@ -312,6 +306,34 @@ func NewLocationEventAgent(locationModel models.LocationModel, eventModel models
|
||||
},
|
||||
}
|
||||
|
||||
toolHandler.Handlers["createEvent"] = ToolHandler[CreateEventArguments, model.Events]{
|
||||
FunctionName: "createEvent",
|
||||
Parse: func(stringArgs string) (CreateEventArguments, error) {
|
||||
args := CreateEventArguments{}
|
||||
err := json.Unmarshal([]byte(stringArgs), &args)
|
||||
|
||||
return args, err
|
||||
},
|
||||
Fn: func(info ToolHandlerInfo, args CreateEventArguments, call ToolCall) (model.Events, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
event, err := agent.eventModel.Save(ctx, info.userId, model.Events{
|
||||
Name: args.Name,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return event, err
|
||||
}
|
||||
|
||||
locationId, err := uuid.Parse(args.LocationId)
|
||||
if err != nil {
|
||||
return event, err
|
||||
}
|
||||
|
||||
return agent.eventModel.UpdateLocation(ctx, event.ID, locationId)
|
||||
},
|
||||
}
|
||||
|
||||
agent.toolHandler = toolHandler
|
||||
|
||||
return agent, nil
|
||||
|
@ -167,12 +167,12 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
err = eventModel.SaveToImage(ctx, userImage.ImageID, imageInfo.Events)
|
||||
if err != nil {
|
||||
log.Println("Failed to save events")
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
// err = eventModel.SaveToImage(ctx, userImage.ImageID, imageInfo.Events)
|
||||
// if err != nil {
|
||||
// log.Println("Failed to save events")
|
||||
// log.Println(err)
|
||||
// return
|
||||
// }
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package models
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"log"
|
||||
. "github.com/go-jet/jet/v2/postgres"
|
||||
"screenmark/screenmark/.gen/haystack/haystack/model"
|
||||
. "screenmark/screenmark/.gen/haystack/haystack/table"
|
||||
|
||||
@ -14,49 +14,32 @@ type EventModel struct {
|
||||
dbPool *sql.DB
|
||||
}
|
||||
|
||||
// This looks stupid
|
||||
func getEventValues(event model.Events) []any {
|
||||
arr := make([]any, 0)
|
||||
|
||||
if event.Description != nil {
|
||||
arr = append(arr, *event.Description)
|
||||
} else {
|
||||
arr = append(arr, nil)
|
||||
}
|
||||
|
||||
if event.LocationID != nil {
|
||||
arr = append(arr, *event.LocationID)
|
||||
} else {
|
||||
arr = append(arr, nil)
|
||||
}
|
||||
|
||||
return arr
|
||||
}
|
||||
|
||||
func (m EventModel) Save(ctx context.Context, events []model.Events) (model.Events, error) {
|
||||
func (m EventModel) Save(ctx context.Context, userId uuid.UUID, event model.Events) (model.Events, error) {
|
||||
// TODO tx here
|
||||
insertEventStmt := Events.
|
||||
INSERT(Events.Name, Events.Description)
|
||||
|
||||
for _, event := range events {
|
||||
insertEventStmt = insertEventStmt.VALUES(event.Name, getEventValues(event)...)
|
||||
}
|
||||
|
||||
insertEventStmt = insertEventStmt.RETURNING(Events.AllColumns)
|
||||
|
||||
log.Println(insertEventStmt.DebugSql())
|
||||
INSERT(Events.Name, Events.Description).
|
||||
VALUES(event.Name, event.Description).
|
||||
RETURNING(Events.AllColumns)
|
||||
|
||||
insertedEvent := model.Events{}
|
||||
err := insertEventStmt.QueryContext(ctx, m.dbPool, &insertedEvent)
|
||||
|
||||
if err != nil {
|
||||
return insertedEvent, err
|
||||
}
|
||||
|
||||
func (m EventModel) SaveToImage(ctx context.Context, imageId uuid.UUID, events []model.Events) error {
|
||||
if len(events) == 0 {
|
||||
return nil
|
||||
insertUserEventStmt := UserEvents.
|
||||
INSERT(UserEvents.UserID, UserEvents.EventID).
|
||||
VALUES(userId, insertedEvent.ID).
|
||||
RETURNING(UserEvents.AllColumns)
|
||||
|
||||
_, err = insertUserEventStmt.ExecContext(ctx, m.dbPool)
|
||||
|
||||
return insertedEvent, err
|
||||
}
|
||||
|
||||
event, err := m.Save(ctx, events)
|
||||
func (m EventModel) SaveToImage(ctx context.Context, userId uuid.UUID, imageId uuid.UUID, event model.Events) error {
|
||||
event, err := m.Save(ctx, userId, event)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
@ -71,6 +54,19 @@ func (m EventModel) SaveToImage(ctx context.Context, imageId uuid.UUID, events [
|
||||
return err
|
||||
}
|
||||
|
||||
func (m EventModel) UpdateLocation(ctx context.Context, eventId uuid.UUID, locationId uuid.UUID) (model.Events, error) {
|
||||
updateEventLocationStmt := Events.
|
||||
UPDATE(Events.LocationID).
|
||||
SET(locationId).
|
||||
WHERE(Events.ID.EQ(UUID(eventId))).
|
||||
RETURNING(Events.AllColumns)
|
||||
|
||||
updatedEvent := model.Events{}
|
||||
err := updateEventLocationStmt.QueryContext(ctx, m.dbPool, &updatedEvent)
|
||||
|
||||
return updatedEvent, err
|
||||
}
|
||||
|
||||
func NewEventModel(db *sql.DB) EventModel {
|
||||
return EventModel{dbPool: db}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package models
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"log"
|
||||
"screenmark/screenmark/.gen/haystack/haystack/model"
|
||||
. "screenmark/screenmark/.gen/haystack/haystack/table"
|
||||
|
||||
@ -57,7 +56,7 @@ func (m LocationModel) SaveToImage(ctx context.Context, imageId uuid.UUID, locat
|
||||
VALUES(imageId, locationId)
|
||||
|
||||
imageLocation := model.ImageLocations{}
|
||||
_, err := insertImageLocationStmt.ExecContext(ctx, m.dbPool)
|
||||
err := insertImageLocationStmt.QueryContext(ctx, m.dbPool, &imageLocation)
|
||||
|
||||
return imageLocation, err
|
||||
}
|
||||
|
@ -86,6 +86,12 @@ CREATE TABLE haystack.image_events (
|
||||
image_id UUID NOT NULL REFERENCES haystack.image (id)
|
||||
);
|
||||
|
||||
CREATE TABLE haystack.user_events (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
event_id UUID NOT NULL REFERENCES haystack.events (id),
|
||||
user_id UUID NOT NULL REFERENCES haystack.users (id)
|
||||
);
|
||||
|
||||
/* -----| Indexes |----- */
|
||||
|
||||
CREATE INDEX user_tags_index ON haystack.user_tags(tag);
|
||||
|
Reference in New Issue
Block a user