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)
|
ImageTags = ImageTags.FromSchema(schema)
|
||||||
ImageText = ImageText.FromSchema(schema)
|
ImageText = ImageText.FromSchema(schema)
|
||||||
Locations = Locations.FromSchema(schema)
|
Locations = Locations.FromSchema(schema)
|
||||||
|
UserEvents = UserEvents.FromSchema(schema)
|
||||||
UserImages = UserImages.FromSchema(schema)
|
UserImages = UserImages.FromSchema(schema)
|
||||||
UserImagesToProcess = UserImagesToProcess.FromSchema(schema)
|
UserImagesToProcess = UserImagesToProcess.FromSchema(schema)
|
||||||
UserLocations = UserLocations.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.
|
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.
|
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.
|
// 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",
|
"type": "function",
|
||||||
"function": {
|
"function": {
|
||||||
@ -139,6 +125,12 @@ type AttachImageLocationArguments struct {
|
|||||||
LocationId string `json:"locationId"`
|
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 {
|
func (agent EventLocationAgent) GetLocations(userId uuid.UUID, imageId uuid.UUID, imageName string, imageData []byte) error {
|
||||||
var tools any
|
var tools any
|
||||||
err := json.Unmarshal([]byte(TOOLS), &tools)
|
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]{
|
toolHandler.Handlers["attachImageLocation"] = ToolHandler[AttachImageLocationArguments, model.ImageLocations]{
|
||||||
FunctionName: "attachImageLocation",
|
FunctionName: "attachImageLocation",
|
||||||
Parse: func(stringArgs string) (AttachImageLocationArguments, error) {
|
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
|
agent.toolHandler = toolHandler
|
||||||
|
|
||||||
return agent, nil
|
return agent, nil
|
||||||
|
@ -167,12 +167,12 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = eventModel.SaveToImage(ctx, userImage.ImageID, imageInfo.Events)
|
// err = eventModel.SaveToImage(ctx, userImage.ImageID, imageInfo.Events)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
log.Println("Failed to save events")
|
// log.Println("Failed to save events")
|
||||||
log.Println(err)
|
// log.Println(err)
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ package models
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"log"
|
. "github.com/go-jet/jet/v2/postgres"
|
||||||
"screenmark/screenmark/.gen/haystack/haystack/model"
|
"screenmark/screenmark/.gen/haystack/haystack/model"
|
||||||
. "screenmark/screenmark/.gen/haystack/haystack/table"
|
. "screenmark/screenmark/.gen/haystack/haystack/table"
|
||||||
|
|
||||||
@ -14,49 +14,32 @@ type EventModel struct {
|
|||||||
dbPool *sql.DB
|
dbPool *sql.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
// This looks stupid
|
func (m EventModel) Save(ctx context.Context, userId uuid.UUID, event model.Events) (model.Events, error) {
|
||||||
func getEventValues(event model.Events) []any {
|
// TODO tx here
|
||||||
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) {
|
|
||||||
insertEventStmt := Events.
|
insertEventStmt := Events.
|
||||||
INSERT(Events.Name, Events.Description)
|
INSERT(Events.Name, Events.Description).
|
||||||
|
VALUES(event.Name, event.Description).
|
||||||
for _, event := range events {
|
RETURNING(Events.AllColumns)
|
||||||
insertEventStmt = insertEventStmt.VALUES(event.Name, getEventValues(event)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
insertEventStmt = insertEventStmt.RETURNING(Events.AllColumns)
|
|
||||||
|
|
||||||
log.Println(insertEventStmt.DebugSql())
|
|
||||||
|
|
||||||
insertedEvent := model.Events{}
|
insertedEvent := model.Events{}
|
||||||
err := insertEventStmt.QueryContext(ctx, m.dbPool, &insertedEvent)
|
err := insertEventStmt.QueryContext(ctx, m.dbPool, &insertedEvent)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
return insertedEvent, err
|
return insertedEvent, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m EventModel) SaveToImage(ctx context.Context, imageId uuid.UUID, events []model.Events) error {
|
insertUserEventStmt := UserEvents.
|
||||||
if len(events) == 0 {
|
INSERT(UserEvents.UserID, UserEvents.EventID).
|
||||||
return nil
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -71,6 +54,19 @@ func (m EventModel) SaveToImage(ctx context.Context, imageId uuid.UUID, events [
|
|||||||
return err
|
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 {
|
func NewEventModel(db *sql.DB) EventModel {
|
||||||
return EventModel{dbPool: db}
|
return EventModel{dbPool: db}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package models
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"log"
|
|
||||||
"screenmark/screenmark/.gen/haystack/haystack/model"
|
"screenmark/screenmark/.gen/haystack/haystack/model"
|
||||||
. "screenmark/screenmark/.gen/haystack/haystack/table"
|
. "screenmark/screenmark/.gen/haystack/haystack/table"
|
||||||
|
|
||||||
@ -57,7 +56,7 @@ func (m LocationModel) SaveToImage(ctx context.Context, imageId uuid.UUID, locat
|
|||||||
VALUES(imageId, locationId)
|
VALUES(imageId, locationId)
|
||||||
|
|
||||||
imageLocation := model.ImageLocations{}
|
imageLocation := model.ImageLocations{}
|
||||||
_, err := insertImageLocationStmt.ExecContext(ctx, m.dbPool)
|
err := insertImageLocationStmt.QueryContext(ctx, m.dbPool, &imageLocation)
|
||||||
|
|
||||||
return imageLocation, err
|
return imageLocation, err
|
||||||
}
|
}
|
||||||
|
@ -86,6 +86,12 @@ CREATE TABLE haystack.image_events (
|
|||||||
image_id UUID NOT NULL REFERENCES haystack.image (id)
|
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 |----- */
|
/* -----| Indexes |----- */
|
||||||
|
|
||||||
CREATE INDEX user_tags_index ON haystack.user_tags(tag);
|
CREATE INDEX user_tags_index ON haystack.user_tags(tag);
|
||||||
|
Reference in New Issue
Block a user