refactor(store): replace project and skill models with generated models
Some checks failed
CI / build-and-test (push) Failing after -31m25s

* Update project creation and retrieval to use generated models
* Modify skill addition and listing to utilize generated models
* Refactor thought handling to incorporate generated models
* Adjust tool annotations to align with new model structure
* Update API calls in the UI to use new ResolveSpec-based endpoints
* Enhance stats retrieval logic to aggregate thought metadata
This commit is contained in:
2026-04-26 12:56:32 +02:00
parent da7220ad64
commit db7b152852
53 changed files with 3638 additions and 426 deletions

View File

@@ -8,6 +8,7 @@ import (
"github.com/google/uuid"
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
ext "git.warky.dev/wdevs/amcs/internal/types"
)
@@ -19,9 +20,12 @@ func (db *DB) AddFamilyMember(ctx context.Context, m ext.FamilyMember) (ext.Fami
`, m.Name, nullStr(m.Relationship), m.BirthDate, nullStr(m.Notes))
created := m
if err := row.Scan(&created.ID, &created.CreatedAt); err != nil {
var model generatedmodels.ModelPublicFamilyMembers
if err := row.Scan(&model.ID, &model.CreatedAt); err != nil {
return ext.FamilyMember{}, fmt.Errorf("insert family member: %w", err)
}
created.ID = model.ID.UUID()
created.CreatedAt = model.CreatedAt.Time()
return created, nil
}
@@ -34,14 +38,11 @@ func (db *DB) ListFamilyMembers(ctx context.Context) ([]ext.FamilyMember, error)
var members []ext.FamilyMember
for rows.Next() {
var m ext.FamilyMember
var relationship, notes *string
if err := rows.Scan(&m.ID, &m.Name, &relationship, &m.BirthDate, &notes, &m.CreatedAt); err != nil {
var model generatedmodels.ModelPublicFamilyMembers
if err := rows.Scan(&model.ID, &model.Name, &model.Relationship, &model.BirthDate, &model.Notes, &model.CreatedAt); err != nil {
return nil, fmt.Errorf("scan family member: %w", err)
}
m.Relationship = strVal(relationship)
m.Notes = strVal(notes)
members = append(members, m)
members = append(members, familyMemberFromModel(model))
}
return members, rows.Err()
}
@@ -56,9 +57,12 @@ func (db *DB) AddActivity(ctx context.Context, a ext.Activity) (ext.Activity, er
nullStr(a.Location), nullStr(a.Notes))
created := a
if err := row.Scan(&created.ID, &created.CreatedAt); err != nil {
var model generatedmodels.ModelPublicActivities
if err := row.Scan(&model.ID, &model.CreatedAt); err != nil {
return ext.Activity{}, fmt.Errorf("insert activity: %w", err)
}
created.ID = model.ID.UUID()
created.CreatedAt = model.CreatedAt.Time()
return created, nil
}
@@ -129,9 +133,12 @@ func (db *DB) AddImportantDate(ctx context.Context, d ext.ImportantDate) (ext.Im
`, d.FamilyMemberID, d.Title, d.DateValue, d.RecurringYearly, d.ReminderDaysBefore, nullStr(d.Notes))
created := d
if err := row.Scan(&created.ID, &created.CreatedAt); err != nil {
var model generatedmodels.ModelPublicImportantDates
if err := row.Scan(&model.ID, &model.CreatedAt); err != nil {
return ext.ImportantDate{}, fmt.Errorf("insert important date: %w", err)
}
created.ID = model.ID.UUID()
created.CreatedAt = model.CreatedAt.Time()
return created, nil
}
@@ -164,17 +171,13 @@ func (db *DB) GetUpcomingDates(ctx context.Context, daysAhead int) ([]ext.Import
var dates []ext.ImportantDate
for rows.Next() {
var d ext.ImportantDate
var memberID *uuid.UUID
var memberName, notes *string
if err := rows.Scan(&d.ID, &memberID, &memberName, &d.Title, &d.DateValue,
&d.RecurringYearly, &d.ReminderDaysBefore, &notes, &d.CreatedAt); err != nil {
var model generatedmodels.ModelPublicImportantDates
var memberName *string
if err := rows.Scan(&model.ID, &model.FamilyMemberID, &memberName, &model.Title, &model.DateValue,
&model.RecurringYearly, &model.ReminderDaysBefore, &model.Notes, &model.CreatedAt); err != nil {
return nil, fmt.Errorf("scan important date: %w", err)
}
d.FamilyMemberID = memberID
d.MemberName = strVal(memberName)
d.Notes = strVal(notes)
dates = append(dates, d)
dates = append(dates, importantDateFromModel(model, strVal(memberName)))
}
return dates, rows.Err()
}
@@ -188,23 +191,16 @@ func scanActivities(rows interface {
defer rows.Close()
var activities []ext.Activity
for rows.Next() {
var a ext.Activity
var memberName, activityType, dayOfWeek, startTime, endTime, location, notes *string
var model generatedmodels.ModelPublicActivities
var memberName *string
if err := rows.Scan(
&a.ID, &a.FamilyMemberID, &memberName, &a.Title, &activityType,
&dayOfWeek, &startTime, &endTime,
&a.StartDate, &a.EndDate, &location, &notes, &a.CreatedAt,
&model.ID, &model.FamilyMemberID, &memberName, &model.Title, &model.ActivityType,
&model.DayOfWeek, &model.StartTime, &model.EndTime,
&model.StartDate, &model.EndDate, &model.Location, &model.Notes, &model.CreatedAt,
); err != nil {
return nil, fmt.Errorf("scan activity: %w", err)
}
a.MemberName = strVal(memberName)
a.ActivityType = strVal(activityType)
a.DayOfWeek = strVal(dayOfWeek)
a.StartTime = strVal(startTime)
a.EndTime = strVal(endTime)
a.Location = strVal(location)
a.Notes = strVal(notes)
activities = append(activities, a)
activities = append(activities, activityFromModel(model, strVal(memberName)))
}
return activities, rows.Err()
}

View File

@@ -10,6 +10,7 @@ import (
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
ext "git.warky.dev/wdevs/amcs/internal/types"
)
@@ -34,9 +35,13 @@ func (db *DB) SaveChatHistory(ctx context.Context, h ext.ChatHistory) (ext.ChatH
)
created := h
if err := row.Scan(&created.ID, &created.CreatedAt, &created.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicChatHistories
if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
return ext.ChatHistory{}, fmt.Errorf("insert chat history: %w", err)
}
created.ID = model.ID.UUID()
created.CreatedAt = model.CreatedAt.Time()
created.UpdatedAt = model.UpdatedAt.Time()
return created, nil
}
@@ -157,26 +162,33 @@ type rowScanner interface {
}
func scanChatHistory(row rowScanner) (ext.ChatHistory, error) {
var h ext.ChatHistory
var title, channel, agentID, summary *string
var messagesJSON, metaJSON []byte
var model generatedmodels.ModelPublicChatHistories
if err := row.Scan(
&h.ID, &h.SessionID, &title, &channel, &agentID, &h.ProjectID,
&messagesJSON, &summary, &metaJSON, &h.CreatedAt, &h.UpdatedAt,
&model.ID, &model.SessionID, &model.Title, &model.Channel, &model.AgentID, &model.ProjectID,
&model.Messages, &model.Summary, &model.Metadata, &model.CreatedAt, &model.UpdatedAt,
); err != nil {
return ext.ChatHistory{}, err
}
h.Title = strVal(title)
h.Channel = strVal(channel)
h.AgentID = strVal(agentID)
h.Summary = strVal(summary)
h := ext.ChatHistory{
ID: model.ID.UUID(),
SessionID: model.SessionID.String(),
Title: model.Title.String(),
Channel: model.Channel.String(),
AgentID: model.AgentID.String(),
Summary: model.Summary.String(),
CreatedAt: model.CreatedAt.Time(),
UpdatedAt: model.UpdatedAt.Time(),
}
if model.ProjectID.Valid {
id := model.ProjectID.UUID()
h.ProjectID = &id
}
if err := json.Unmarshal(messagesJSON, &h.Messages); err != nil {
if err := json.Unmarshal(model.Messages, &h.Messages); err != nil {
return ext.ChatHistory{}, fmt.Errorf("unmarshal messages: %w", err)
}
if err := json.Unmarshal(metaJSON, &h.Metadata); err != nil {
if err := json.Unmarshal(model.Metadata, &h.Metadata); err != nil {
return ext.ChatHistory{}, fmt.Errorf("unmarshal metadata: %w", err)
}
if h.Messages == nil {

View File

@@ -8,6 +8,7 @@ import (
"github.com/google/uuid"
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
ext "git.warky.dev/wdevs/amcs/internal/types"
)
@@ -24,9 +25,13 @@ func (db *DB) AddProfessionalContact(ctx context.Context, c ext.ProfessionalCont
nullStr(c.LinkedInURL), nullStr(c.HowWeMet), c.Tags, nullStr(c.Notes), c.FollowUpDate)
created := c
if err := row.Scan(&created.ID, &created.CreatedAt, &created.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicProfessionalContacts
if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
return ext.ProfessionalContact{}, fmt.Errorf("insert contact: %w", err)
}
created.ID = model.ID.UUID()
created.CreatedAt = model.CreatedAt.Time()
created.UpdatedAt = model.UpdatedAt.Time()
return created, nil
}
@@ -45,7 +50,7 @@ func (db *DB) SearchContacts(ctx context.Context, query string, tags []string) (
conditions = append(conditions, fmt.Sprintf("tags @> $%d", len(args)))
}
q := `select id, name, company, title, email, phone, linkedin_url, how_we_met, tags, notes, last_contacted, follow_up_date, created_at, updated_at from professional_contacts`
q := `select id, name, company, title, email, phone, linkedin_url, how_we_met, tags::text[], notes, last_contacted, follow_up_date, created_at, updated_at from professional_contacts`
if len(conditions) > 0 {
q += " where " + strings.Join(conditions, " and ")
}
@@ -62,27 +67,18 @@ func (db *DB) SearchContacts(ctx context.Context, query string, tags []string) (
func (db *DB) GetContact(ctx context.Context, id uuid.UUID) (ext.ProfessionalContact, error) {
row := db.pool.QueryRow(ctx, `
select id, name, company, title, email, phone, linkedin_url, how_we_met, tags, notes, last_contacted, follow_up_date, created_at, updated_at
select id, name, company, title, email, phone, linkedin_url, how_we_met, tags::text[], notes, last_contacted, follow_up_date, created_at, updated_at
from professional_contacts where id = $1
`, id)
var c ext.ProfessionalContact
var company, title, email, phone, linkedInURL, howWeMet, notes *string
if err := row.Scan(&c.ID, &c.Name, &company, &title, &email, &phone,
&linkedInURL, &howWeMet, &c.Tags, &notes, &c.LastContacted, &c.FollowUpDate,
&c.CreatedAt, &c.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicProfessionalContacts
var tags []string
if err := row.Scan(&model.ID, &model.Name, &model.Company, &model.Title, &model.Email, &model.Phone,
&model.LinkedinURL, &model.HowWeMet, &tags, &model.Notes, &model.LastContacted, &model.FollowUpDate,
&model.CreatedAt, &model.UpdatedAt); err != nil {
return ext.ProfessionalContact{}, fmt.Errorf("get contact: %w", err)
}
c.Company = strVal(company)
c.Title = strVal(title)
c.Email = strVal(email)
c.Phone = strVal(phone)
c.LinkedInURL = strVal(linkedInURL)
c.HowWeMet = strVal(howWeMet)
c.Notes = strVal(notes)
if c.Tags == nil {
c.Tags = []string{}
}
c := professionalContactFromModel(model, tags)
return c, nil
}
@@ -101,9 +97,12 @@ func (db *DB) LogInteraction(ctx context.Context, interaction ext.ContactInterac
created := interaction
created.OccurredAt = occurredAt
if err := row.Scan(&created.ID, &created.CreatedAt); err != nil {
var model generatedmodels.ModelPublicContactInteractions
if err := row.Scan(&model.ID, &model.CreatedAt); err != nil {
return ext.ContactInteraction{}, fmt.Errorf("insert interaction: %w", err)
}
created.ID = model.ID.UUID()
created.CreatedAt = model.CreatedAt.Time()
return created, nil
}
@@ -124,14 +123,12 @@ func (db *DB) GetContactHistory(ctx context.Context, contactID uuid.UUID) (ext.C
var interactions []ext.ContactInteraction
for rows.Next() {
var i ext.ContactInteraction
var followUpNotes *string
if err := rows.Scan(&i.ID, &i.ContactID, &i.InteractionType, &i.OccurredAt, &i.Summary,
&i.FollowUpNeeded, &followUpNotes, &i.CreatedAt); err != nil {
var model generatedmodels.ModelPublicContactInteractions
if err := rows.Scan(&model.ID, &model.ContactID, &model.InteractionType, &model.OccurredAt, &model.Summary,
&model.FollowUpNeeded, &model.FollowUpNotes, &model.CreatedAt); err != nil {
return ext.ContactHistory{}, fmt.Errorf("scan interaction: %w", err)
}
i.FollowUpNotes = strVal(followUpNotes)
interactions = append(interactions, i)
interactions = append(interactions, contactInteractionFromModel(model))
}
if err := rows.Err(); err != nil {
return ext.ContactHistory{}, err
@@ -148,15 +145,12 @@ func (db *DB) GetContactHistory(ctx context.Context, contactID uuid.UUID) (ext.C
var opportunities []ext.Opportunity
for oppRows.Next() {
var o ext.Opportunity
var description, notes *string
if err := oppRows.Scan(&o.ID, &o.ContactID, &o.Title, &description, &o.Stage, &o.Value,
&o.ExpectedCloseDate, &notes, &o.CreatedAt, &o.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicOpportunities
if err := oppRows.Scan(&model.ID, &model.ContactID, &model.Title, &model.Description, &model.Stage, &model.Value,
&model.ExpectedCloseDate, &model.Notes, &model.CreatedAt, &model.UpdatedAt); err != nil {
return ext.ContactHistory{}, fmt.Errorf("scan opportunity: %w", err)
}
o.Description = strVal(description)
o.Notes = strVal(notes)
opportunities = append(opportunities, o)
opportunities = append(opportunities, opportunityFromModel(model))
}
if err := oppRows.Err(); err != nil {
return ext.ContactHistory{}, err
@@ -177,9 +171,13 @@ func (db *DB) CreateOpportunity(ctx context.Context, o ext.Opportunity) (ext.Opp
`, o.ContactID, o.Title, nullStr(o.Description), o.Stage, o.Value, o.ExpectedCloseDate, nullStr(o.Notes))
created := o
if err := row.Scan(&created.ID, &created.CreatedAt, &created.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicOpportunities
if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
return ext.Opportunity{}, fmt.Errorf("insert opportunity: %w", err)
}
created.ID = model.ID.UUID()
created.CreatedAt = model.CreatedAt.Time()
created.UpdatedAt = model.UpdatedAt.Time()
return created, nil
}
@@ -190,7 +188,7 @@ func (db *DB) GetFollowUpsDue(ctx context.Context, daysAhead int) ([]ext.Profess
cutoff := time.Now().AddDate(0, 0, daysAhead)
rows, err := db.pool.Query(ctx, `
select id, name, company, title, email, phone, linkedin_url, how_we_met, tags, notes, last_contacted, follow_up_date, created_at, updated_at
select id, name, company, title, email, phone, linkedin_url, how_we_met, tags::text[], notes, last_contacted, follow_up_date, created_at, updated_at
from professional_contacts
where follow_up_date <= $1
order by follow_up_date asc
@@ -224,24 +222,14 @@ func scanContacts(rows interface {
defer rows.Close()
var contacts []ext.ProfessionalContact
for rows.Next() {
var c ext.ProfessionalContact
var company, title, email, phone, linkedInURL, howWeMet, notes *string
if err := rows.Scan(&c.ID, &c.Name, &company, &title, &email, &phone,
&linkedInURL, &howWeMet, &c.Tags, &notes, &c.LastContacted, &c.FollowUpDate,
&c.CreatedAt, &c.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicProfessionalContacts
var tags []string
if err := rows.Scan(&model.ID, &model.Name, &model.Company, &model.Title, &model.Email, &model.Phone,
&model.LinkedinURL, &model.HowWeMet, &tags, &model.Notes, &model.LastContacted, &model.FollowUpDate,
&model.CreatedAt, &model.UpdatedAt); err != nil {
return nil, fmt.Errorf("scan contact: %w", err)
}
c.Company = strVal(company)
c.Title = strVal(title)
c.Email = strVal(email)
c.Phone = strVal(phone)
c.LinkedInURL = strVal(linkedInURL)
c.HowWeMet = strVal(howWeMet)
c.Notes = strVal(notes)
if c.Tags == nil {
c.Tags = []string{}
}
contacts = append(contacts, c)
contacts = append(contacts, professionalContactFromModel(model, tags))
}
return contacts, rows.Err()
}

View File

@@ -2,18 +2,23 @@ package store
import (
"context"
"database/sql"
"fmt"
"time"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
pgxvec "github.com/pgvector/pgvector-go/pgx"
"github.com/uptrace/bun"
"github.com/uptrace/bun/dialect/pgdialect"
"github.com/uptrace/bun/driver/pgdriver"
"git.warky.dev/wdevs/amcs/internal/config"
)
type DB struct {
pool *pgxpool.Pool
bun *bun.DB
}
func New(ctx context.Context, cfg config.DatabaseConfig) (*DB, error) {
@@ -35,8 +40,20 @@ func New(ctx context.Context, cfg config.DatabaseConfig) (*DB, error) {
return nil, fmt.Errorf("create database pool: %w", err)
}
db := &DB{pool: pool}
bunSQLDB := sql.OpenDB(pgdriver.NewConnector(pgdriver.WithDSN(cfg.URL)))
bunSQLDB.SetMaxOpenConns(int(cfg.MaxConns))
bunSQLDB.SetMaxIdleConns(int(cfg.MinConns))
bunSQLDB.SetConnMaxLifetime(cfg.MaxConnLifetime)
bunSQLDB.SetConnMaxIdleTime(cfg.MaxConnIdleTime)
db := &DB{
pool: pool,
bun: bun.NewDB(bunSQLDB, pgdialect.New()),
}
if err := db.Ping(ctx); err != nil {
if db.bun != nil {
_ = db.bun.Close()
}
pool.Close()
return nil, err
}
@@ -45,11 +62,16 @@ func New(ctx context.Context, cfg config.DatabaseConfig) (*DB, error) {
}
func (db *DB) Close() {
if db == nil || db.pool == nil {
if db == nil {
return
}
db.pool.Close()
if db.bun != nil {
_ = db.bun.Close()
}
if db.pool != nil {
db.pool.Close()
}
}
func (db *DB) Ping(ctx context.Context) error {
@@ -102,3 +124,10 @@ func (db *DB) VerifyRequirements(ctx context.Context) error {
return nil
}
func (db *DB) Bun() *bun.DB {
if db == nil {
return nil
}
return db.bun
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
thoughttypes "git.warky.dev/wdevs/amcs/internal/types"
)
@@ -19,24 +20,24 @@ func (db *DB) InsertStoredFile(ctx context.Context, file thoughttypes.StoredFile
returning guid, thought_id, project_id, name, media_type, kind, encoding, size_bytes, sha256, created_at, updated_at
`, file.ThoughtID, file.ProjectID, file.Name, file.MediaType, file.Kind, file.Encoding, file.SizeBytes, file.SHA256, file.Content)
var created thoughttypes.StoredFile
var model generatedmodels.ModelPublicStoredFiles
if err := row.Scan(
&created.ID,
&created.ThoughtID,
&created.ProjectID,
&created.Name,
&created.MediaType,
&created.Kind,
&created.Encoding,
&created.SizeBytes,
&created.SHA256,
&created.CreatedAt,
&created.UpdatedAt,
&model.GUID,
&model.ThoughtID,
&model.ProjectID,
&model.Name,
&model.MediaType,
&model.Kind,
&model.Encoding,
&model.SizeBytes,
&model.Sha256,
&model.CreatedAt,
&model.UpdatedAt,
); err != nil {
return thoughttypes.StoredFile{}, fmt.Errorf("insert stored file: %w", err)
}
return created, nil
return storedFileFromModel(model), nil
}
func (db *DB) GetStoredFile(ctx context.Context, id uuid.UUID) (thoughttypes.StoredFile, error) {
@@ -46,20 +47,20 @@ func (db *DB) GetStoredFile(ctx context.Context, id uuid.UUID) (thoughttypes.Sto
where guid = $1
`, id)
var file thoughttypes.StoredFile
var model generatedmodels.ModelPublicStoredFiles
if err := row.Scan(
&file.ID,
&file.ThoughtID,
&file.ProjectID,
&file.Name,
&file.MediaType,
&file.Kind,
&file.Encoding,
&file.SizeBytes,
&file.SHA256,
&file.Content,
&file.CreatedAt,
&file.UpdatedAt,
&model.GUID,
&model.ThoughtID,
&model.ProjectID,
&model.Name,
&model.MediaType,
&model.Kind,
&model.Encoding,
&model.SizeBytes,
&model.Sha256,
&model.Content,
&model.CreatedAt,
&model.UpdatedAt,
); err != nil {
if err == pgx.ErrNoRows {
return thoughttypes.StoredFile{}, err
@@ -67,7 +68,7 @@ func (db *DB) GetStoredFile(ctx context.Context, id uuid.UUID) (thoughttypes.Sto
return thoughttypes.StoredFile{}, fmt.Errorf("get stored file: %w", err)
}
return file, nil
return storedFileFromModel(model), nil
}
func (db *DB) ListStoredFiles(ctx context.Context, filter thoughttypes.StoredFileFilter) ([]thoughttypes.StoredFile, error) {
@@ -106,23 +107,23 @@ func (db *DB) ListStoredFiles(ctx context.Context, filter thoughttypes.StoredFil
files := make([]thoughttypes.StoredFile, 0, filter.Limit)
for rows.Next() {
var file thoughttypes.StoredFile
var model generatedmodels.ModelPublicStoredFiles
if err := rows.Scan(
&file.ID,
&file.ThoughtID,
&file.ProjectID,
&file.Name,
&file.MediaType,
&file.Kind,
&file.Encoding,
&file.SizeBytes,
&file.SHA256,
&file.CreatedAt,
&file.UpdatedAt,
&model.GUID,
&model.ThoughtID,
&model.ProjectID,
&model.Name,
&model.MediaType,
&model.Kind,
&model.Encoding,
&model.SizeBytes,
&model.Sha256,
&model.CreatedAt,
&model.UpdatedAt,
); err != nil {
return nil, fmt.Errorf("scan stored file: %w", err)
}
files = append(files, file)
files = append(files, storedFileFromModel(model))
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("iterate stored files: %w", err)

View File

@@ -5,10 +5,10 @@ import (
"encoding/json"
"fmt"
"strings"
"time"
"github.com/google/uuid"
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
ext "git.warky.dev/wdevs/amcs/internal/types"
)
@@ -25,9 +25,13 @@ func (db *DB) AddHouseholdItem(ctx context.Context, item ext.HouseholdItem) (ext
`, item.Name, nullStr(item.Category), nullStr(item.Location), details, nullStr(item.Notes))
created := item
if err := row.Scan(&created.ID, &created.CreatedAt, &created.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicHouseholdItems
if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
return ext.HouseholdItem{}, fmt.Errorf("insert household item: %w", err)
}
created.ID = model.ID.UUID()
created.CreatedAt = model.CreatedAt.Time()
created.UpdatedAt = model.UpdatedAt.Time()
return created, nil
}
@@ -62,19 +66,11 @@ func (db *DB) SearchHouseholdItems(ctx context.Context, query, category, locatio
var items []ext.HouseholdItem
for rows.Next() {
var item ext.HouseholdItem
var detailsBytes []byte
var category, location, notes *string
if err := rows.Scan(&item.ID, &item.Name, &category, &location, &detailsBytes, &notes, &item.CreatedAt, &item.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicHouseholdItems
if err := rows.Scan(&model.ID, &model.Name, &model.Category, &model.Location, &model.Details, &model.Notes, &model.CreatedAt, &model.UpdatedAt); err != nil {
return nil, fmt.Errorf("scan household item: %w", err)
}
item.Category = strVal(category)
item.Location = strVal(location)
item.Notes = strVal(notes)
if err := json.Unmarshal(detailsBytes, &item.Details); err != nil {
item.Details = map[string]any{}
}
items = append(items, item)
items = append(items, householdItemFromModel(model))
}
return items, rows.Err()
}
@@ -85,19 +81,11 @@ func (db *DB) GetHouseholdItem(ctx context.Context, id uuid.UUID) (ext.Household
from household_items where id = $1
`, id)
var item ext.HouseholdItem
var detailsBytes []byte
var category, location, notes *string
if err := row.Scan(&item.ID, &item.Name, &category, &location, &detailsBytes, &notes, &item.CreatedAt, &item.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicHouseholdItems
if err := row.Scan(&model.ID, &model.Name, &model.Category, &model.Location, &model.Details, &model.Notes, &model.CreatedAt, &model.UpdatedAt); err != nil {
return ext.HouseholdItem{}, fmt.Errorf("get household item: %w", err)
}
item.Category = strVal(category)
item.Location = strVal(location)
item.Notes = strVal(notes)
if err := json.Unmarshal(detailsBytes, &item.Details); err != nil {
item.Details = map[string]any{}
}
return item, nil
return householdItemFromModel(model), nil
}
func (db *DB) AddVendor(ctx context.Context, v ext.HouseholdVendor) (ext.HouseholdVendor, error) {
@@ -109,9 +97,12 @@ func (db *DB) AddVendor(ctx context.Context, v ext.HouseholdVendor) (ext.Househo
nullStr(v.Website), nullStr(v.Notes), v.Rating, v.LastUsed)
created := v
if err := row.Scan(&created.ID, &created.CreatedAt); err != nil {
var model generatedmodels.ModelPublicHouseholdVendors
if err := row.Scan(&model.ID, &model.CreatedAt); err != nil {
return ext.HouseholdVendor{}, fmt.Errorf("insert vendor: %w", err)
}
created.ID = model.ID.UUID()
created.CreatedAt = model.CreatedAt.Time()
return created, nil
}
@@ -132,19 +123,11 @@ func (db *DB) ListVendors(ctx context.Context, serviceType string) ([]ext.Househ
var vendors []ext.HouseholdVendor
for rows.Next() {
var v ext.HouseholdVendor
var serviceType, phone, email, website, notes *string
var lastUsed *time.Time
if err := rows.Scan(&v.ID, &v.Name, &serviceType, &phone, &email, &website, &notes, &v.Rating, &lastUsed, &v.CreatedAt); err != nil {
var model generatedmodels.ModelPublicHouseholdVendors
if err := rows.Scan(&model.ID, &model.Name, &model.ServiceType, &model.Phone, &model.Email, &model.Website, &model.Notes, &model.Rating, &model.LastUsed, &model.CreatedAt); err != nil {
return nil, fmt.Errorf("scan vendor: %w", err)
}
v.ServiceType = strVal(serviceType)
v.Phone = strVal(phone)
v.Email = strVal(email)
v.Website = strVal(website)
v.Notes = strVal(notes)
v.LastUsed = lastUsed
vendors = append(vendors, v)
vendors = append(vendors, householdVendorFromModel(model))
}
return vendors, rows.Err()
}

View File

@@ -5,9 +5,9 @@ import (
"fmt"
"strings"
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
thoughttypes "git.warky.dev/wdevs/amcs/internal/types"
)
@@ -48,9 +48,13 @@ func (db *DB) CreateLearning(ctx context.Context, learning thoughttypes.Learning
)
created := learning
if err := row.Scan(&created.ID, &created.CreatedAt, &created.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicLearnings
if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
return thoughttypes.Learning{}, fmt.Errorf("create learning: %w", err)
}
created.ID = model.ID.UUID()
created.CreatedAt = model.CreatedAt.Time()
created.UpdatedAt = model.UpdatedAt.Time()
return created, nil
}
@@ -59,7 +63,7 @@ func (db *DB) GetLearning(ctx context.Context, id uuid.UUID) (thoughttypes.Learn
select id, summary, details, category, area, status, priority, confidence,
action_required, source_type, source_ref, project_id, related_thought_id,
related_skill_id, reviewed_by, reviewed_at, duplicate_of_learning_id,
supersedes_learning_id, tags, created_at, updated_at
supersedes_learning_id, tags::text[], created_at, updated_at
from learnings
where id = $1
`, id)
@@ -111,7 +115,7 @@ func (db *DB) ListLearnings(ctx context.Context, filter thoughttypes.LearningFil
select id, summary, details, category, area, status, priority, confidence,
action_required, source_type, source_ref, project_id, related_thought_id,
related_skill_id, reviewed_by, reviewed_at, duplicate_of_learning_id,
supersedes_learning_id, tags, created_at, updated_at
supersedes_learning_id, tags::text[], created_at, updated_at
from learnings
`
if len(conditions) > 0 {
@@ -148,51 +152,40 @@ type learningScanner interface {
}
func scanLearning(row learningScanner) (thoughttypes.Learning, error) {
var learning thoughttypes.Learning
var sourceType pgtype.Text
var sourceRef pgtype.Text
var reviewedBy pgtype.Text
var model generatedmodels.ModelPublicLearnings
var tags []string
err := row.Scan(
&learning.ID,
&learning.Summary,
&learning.Details,
&learning.Category,
&learning.Area,
&learning.Status,
&learning.Priority,
&learning.Confidence,
&learning.ActionRequired,
&sourceType,
&sourceRef,
&learning.ProjectID,
&learning.RelatedThoughtID,
&learning.RelatedSkillID,
&reviewedBy,
&learning.ReviewedAt,
&learning.DuplicateOfLearningID,
&learning.SupersedesLearningID,
&model.ID,
&model.Summary,
&model.Details,
&model.Category,
&model.Area,
&model.Status,
&model.Priority,
&model.Confidence,
&model.ActionRequired,
&model.SourceType,
&model.SourceRef,
&model.ProjectID,
&model.RelatedThoughtID,
&model.RelatedSkillID,
&model.ReviewedBy,
&model.ReviewedAt,
&model.DuplicateOfLearningID,
&model.SupersedesLearningID,
&tags,
&learning.CreatedAt,
&learning.UpdatedAt,
&model.CreatedAt,
&model.UpdatedAt,
)
if err != nil {
return thoughttypes.Learning{}, err
}
learning.SourceType = sourceType.String
learning.SourceRef = sourceRef.String
if reviewedBy.Valid {
value := reviewedBy.String
learning.ReviewedBy = &value
}
if tags == nil {
learning.Tags = []string{}
} else {
learning.Tags = tags
tags = []string{}
}
return learning, nil
return learningFromModel(model, tags), nil
}
func nullableText(value string) *string {

View File

@@ -2,11 +2,11 @@ package store
import (
"context"
"encoding/json"
"fmt"
"github.com/google/uuid"
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
thoughttypes "git.warky.dev/wdevs/amcs/internal/types"
)
@@ -44,24 +44,26 @@ func (db *DB) LinkedThoughts(ctx context.Context, thoughtID uuid.UUID) ([]though
links := make([]thoughttypes.LinkedThought, 0)
for rows.Next() {
var linked thoughttypes.LinkedThought
var metadataBytes []byte
var model generatedmodels.ModelPublicThoughts
if err := rows.Scan(
&linked.Thought.ID,
&linked.Thought.Content,
&metadataBytes,
&linked.Thought.ProjectID,
&linked.Thought.ArchivedAt,
&linked.Thought.CreatedAt,
&linked.Thought.UpdatedAt,
&model.GUID,
&model.Content,
&model.Metadata,
&model.ProjectID,
&model.ArchivedAt,
&model.CreatedAt,
&model.UpdatedAt,
&linked.Relation,
&linked.Direction,
&linked.CreatedAt,
); err != nil {
return nil, fmt.Errorf("scan linked thought: %w", err)
}
if err := json.Unmarshal(metadataBytes, &linked.Thought.Metadata); err != nil {
return nil, fmt.Errorf("decode linked thought metadata: %w", err)
thought, err := thoughtFromModel(model)
if err != nil {
return nil, fmt.Errorf("map linked thought: %w", err)
}
linked.Thought = thought
links = append(links, linked)
}
if err := rows.Err(); err != nil {

View File

@@ -6,6 +6,7 @@ import (
"strings"
"time"
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
ext "git.warky.dev/wdevs/amcs/internal/types"
)
@@ -17,9 +18,13 @@ func (db *DB) AddMaintenanceTask(ctx context.Context, t ext.MaintenanceTask) (ex
`, t.Name, nullStr(t.Category), t.FrequencyDays, t.NextDue, t.Priority, nullStr(t.Notes))
created := t
if err := row.Scan(&created.ID, &created.CreatedAt, &created.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicMaintenanceTasks
if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
return ext.MaintenanceTask{}, fmt.Errorf("insert maintenance task: %w", err)
}
created.ID = model.ID.UUID()
created.CreatedAt = model.CreatedAt.Time()
created.UpdatedAt = model.UpdatedAt.Time()
return created, nil
}
@@ -37,9 +42,11 @@ func (db *DB) LogMaintenance(ctx context.Context, log ext.MaintenanceLog) (ext.M
created := log
created.CompletedAt = completedAt
if err := row.Scan(&created.ID); err != nil {
var model generatedmodels.ModelPublicMaintenanceLogs
if err := row.Scan(&model.ID); err != nil {
return ext.MaintenanceLog{}, fmt.Errorf("insert maintenance log: %w", err)
}
created.ID = model.ID.UUID()
return created, nil
}
@@ -60,7 +67,15 @@ func (db *DB) GetUpcomingMaintenance(ctx context.Context, daysAhead int) ([]ext.
}
defer rows.Close()
return scanMaintenanceTasks(rows)
tasks := make([]ext.MaintenanceTask, 0)
for rows.Next() {
var model generatedmodels.ModelPublicMaintenanceTasks
if err := rows.Scan(&model.ID, &model.Name, &model.Category, &model.FrequencyDays, &model.LastCompleted, &model.NextDue, &model.Priority, &model.Notes, &model.CreatedAt, &model.UpdatedAt); err != nil {
return nil, fmt.Errorf("scan maintenance task: %w", err)
}
tasks = append(tasks, maintenanceTaskFromModel(model))
}
return tasks, rows.Err()
}
func (db *DB) SearchMaintenanceHistory(ctx context.Context, query, category string, start, end *time.Time) ([]ext.MaintenanceLogWithTask, error) {
@@ -103,40 +118,20 @@ func (db *DB) SearchMaintenanceHistory(ctx context.Context, query, category stri
var logs []ext.MaintenanceLogWithTask
for rows.Next() {
var l ext.MaintenanceLogWithTask
var performedBy, notes, nextAction, taskCategory *string
var model generatedmodels.ModelPublicMaintenanceLogs
var taskName, taskCategory string
if err := rows.Scan(
&l.ID, &l.TaskID, &l.CompletedAt, &performedBy, &l.Cost, &notes, &nextAction,
&l.TaskName, &taskCategory,
&model.ID, &model.TaskID, &model.CompletedAt, &model.PerformedBy, &model.Cost, &model.Notes, &model.NextAction,
&taskName, &taskCategory,
); err != nil {
return nil, fmt.Errorf("scan maintenance log: %w", err)
}
l.PerformedBy = strVal(performedBy)
l.Notes = strVal(notes)
l.NextAction = strVal(nextAction)
l.TaskCategory = strVal(taskCategory)
l := ext.MaintenanceLogWithTask{
MaintenanceLog: maintenanceLogFromModel(model),
TaskName: taskName,
TaskCategory: taskCategory,
}
logs = append(logs, l)
}
return logs, rows.Err()
}
func scanMaintenanceTasks(rows interface {
Next() bool
Scan(...any) error
Err() error
Close()
}) ([]ext.MaintenanceTask, error) {
defer rows.Close()
var tasks []ext.MaintenanceTask
for rows.Next() {
var t ext.MaintenanceTask
var category, notes *string
if err := rows.Scan(&t.ID, &t.Name, &category, &t.FrequencyDays, &t.LastCompleted, &t.NextDue, &t.Priority, &notes, &t.CreatedAt, &t.UpdatedAt); err != nil {
return nil, fmt.Errorf("scan maintenance task: %w", err)
}
t.Category = strVal(category)
t.Notes = strVal(notes)
tasks = append(tasks, t)
}
return tasks, rows.Err()
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/google/uuid"
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
ext "git.warky.dev/wdevs/amcs/internal/types"
)
@@ -33,9 +34,13 @@ func (db *DB) AddRecipe(ctx context.Context, r ext.Recipe) (ext.Recipe, error) {
ingredients, instructions, r.Tags, r.Rating, nullStr(r.Notes))
created := r
if err := row.Scan(&created.ID, &created.CreatedAt, &created.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicRecipes
if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
return ext.Recipe{}, fmt.Errorf("insert recipe: %w", err)
}
created.ID = model.ID.UUID()
created.CreatedAt = model.CreatedAt.Time()
created.UpdatedAt = model.UpdatedAt.Time()
return created, nil
}
@@ -60,7 +65,7 @@ func (db *DB) SearchRecipes(ctx context.Context, query, cuisine string, tags []s
conditions = append(conditions, fmt.Sprintf("ingredients::text ILIKE $%d", len(args)))
}
q := `select id, name, cuisine, prep_time_minutes, cook_time_minutes, servings, ingredients, instructions, tags, rating, notes, created_at, updated_at from recipes`
q := `select id, name, cuisine, prep_time_minutes, cook_time_minutes, servings, ingredients, instructions, tags::text[], rating, notes, created_at, updated_at from recipes`
if len(conditions) > 0 {
q += " where " + strings.Join(conditions, " and ")
}
@@ -85,29 +90,20 @@ func (db *DB) SearchRecipes(ctx context.Context, query, cuisine string, tags []s
func (db *DB) GetRecipe(ctx context.Context, id uuid.UUID) (ext.Recipe, error) {
row := db.pool.QueryRow(ctx, `
select id, name, cuisine, prep_time_minutes, cook_time_minutes, servings, ingredients, instructions, tags, rating, notes, created_at, updated_at
select id, name, cuisine, prep_time_minutes, cook_time_minutes, servings, ingredients, instructions, tags::text[], rating, notes, created_at, updated_at
from recipes where id = $1
`, id)
var r ext.Recipe
var cuisine, notes *string
var ingredientsBytes, instructionsBytes []byte
if err := row.Scan(&r.ID, &r.Name, &cuisine, &r.PrepTimeMinutes, &r.CookTimeMinutes, &r.Servings,
&ingredientsBytes, &instructionsBytes, &r.Tags, &r.Rating, &notes, &r.CreatedAt, &r.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicRecipes
var tags []string
if err := row.Scan(&model.ID, &model.Name, &model.Cuisine, &model.PrepTimeMinutes, &model.CookTimeMinutes, &model.Servings,
&model.Ingredients, &model.Instructions, &tags, &model.Rating, &model.Notes, &model.CreatedAt, &model.UpdatedAt); err != nil {
return ext.Recipe{}, fmt.Errorf("get recipe: %w", err)
}
r.Cuisine = strVal(cuisine)
r.Notes = strVal(notes)
if r.Tags == nil {
r.Tags = []string{}
if tags == nil {
tags = []string{}
}
if err := json.Unmarshal(ingredientsBytes, &r.Ingredients); err != nil {
r.Ingredients = []ext.Ingredient{}
}
if err := json.Unmarshal(instructionsBytes, &r.Instructions); err != nil {
r.Instructions = []string{}
}
return r, nil
return recipeFromModel(model, tags), nil
}
func (db *DB) UpdateRecipe(ctx context.Context, id uuid.UUID, r ext.Recipe) (ext.Recipe, error) {
@@ -159,9 +155,12 @@ func (db *DB) CreateMealPlan(ctx context.Context, weekStart time.Time, entries [
Servings: e.Servings,
Notes: e.Notes,
}
if err := row.Scan(&entry.ID, &entry.CreatedAt); err != nil {
var model generatedmodels.ModelPublicMealPlans
if err := row.Scan(&model.ID, &model.CreatedAt); err != nil {
return nil, fmt.Errorf("insert meal plan entry: %w", err)
}
entry.ID = model.ID.UUID()
entry.CreatedAt = model.CreatedAt.Time()
results = append(results, entry)
}
return results, nil
@@ -191,15 +190,12 @@ func (db *DB) GetMealPlan(ctx context.Context, weekStart time.Time) ([]ext.MealP
var entries []ext.MealPlanEntry
for rows.Next() {
var e ext.MealPlanEntry
var recipeName, customMeal, notes *string
if err := rows.Scan(&e.ID, &e.WeekStart, &e.DayOfWeek, &e.MealType, &e.RecipeID, &recipeName, &customMeal, &e.Servings, &notes, &e.CreatedAt); err != nil {
var model generatedmodels.ModelPublicMealPlans
var recipeName *string
if err := rows.Scan(&model.ID, &model.WeekStart, &model.DayOfWeek, &model.MealType, &model.RecipeID, &recipeName, &model.CustomMeal, &model.Servings, &model.Notes, &model.CreatedAt); err != nil {
return nil, fmt.Errorf("scan meal plan entry: %w", err)
}
e.RecipeName = strVal(recipeName)
e.CustomMeal = strVal(customMeal)
e.Notes = strVal(notes)
entries = append(entries, e)
entries = append(entries, mealPlanEntryFromModel(model, strVal(recipeName)))
}
return entries, rows.Err()
}
@@ -259,31 +255,26 @@ func (db *DB) GenerateShoppingList(ctx context.Context, weekStart time.Time) (ex
returning id, created_at, updated_at
`, weekStart, itemsJSON)
var model generatedmodels.ModelPublicShoppingLists
list := ext.ShoppingList{WeekStart: weekStart, Items: items}
if err := row.Scan(&list.ID, &list.CreatedAt, &list.UpdatedAt); err != nil {
if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
return ext.ShoppingList{}, fmt.Errorf("upsert shopping list: %w", err)
}
list.ID = model.ID.UUID()
list.CreatedAt = model.CreatedAt.Time()
list.UpdatedAt = model.UpdatedAt.Time()
return list, nil
}
func scanRecipeRow(rows interface{ Scan(...any) error }) (ext.Recipe, error) {
var r ext.Recipe
var cuisine, notes *string
var ingredientsBytes, instructionsBytes []byte
if err := rows.Scan(&r.ID, &r.Name, &cuisine, &r.PrepTimeMinutes, &r.CookTimeMinutes, &r.Servings,
&ingredientsBytes, &instructionsBytes, &r.Tags, &r.Rating, &notes, &r.CreatedAt, &r.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicRecipes
var tags []string
if err := rows.Scan(&model.ID, &model.Name, &model.Cuisine, &model.PrepTimeMinutes, &model.CookTimeMinutes, &model.Servings,
&model.Ingredients, &model.Instructions, &tags, &model.Rating, &model.Notes, &model.CreatedAt, &model.UpdatedAt); err != nil {
return ext.Recipe{}, fmt.Errorf("scan recipe: %w", err)
}
r.Cuisine = strVal(cuisine)
r.Notes = strVal(notes)
if r.Tags == nil {
r.Tags = []string{}
if tags == nil {
tags = []string{}
}
if err := json.Unmarshal(ingredientsBytes, &r.Ingredients); err != nil {
r.Ingredients = []ext.Ingredient{}
}
if err := json.Unmarshal(instructionsBytes, &r.Instructions); err != nil {
r.Instructions = []string{}
}
return r, nil
return recipeFromModel(model, tags), nil
}

View File

@@ -0,0 +1,487 @@
package store
import (
"encoding/json"
"fmt"
"time"
"github.com/google/uuid"
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
ext "git.warky.dev/wdevs/amcs/internal/types"
)
func projectFromModel(m generatedmodels.ModelPublicProjects) ext.Project {
return ext.Project{
ID: m.GUID.UUID(),
Name: m.Name.String(),
Description: m.Description.String(),
CreatedAt: m.CreatedAt.Time(),
LastActiveAt: m.LastActiveAt.Time(),
}
}
func thoughtFromModel(m generatedmodels.ModelPublicThoughts) (ext.Thought, error) {
var metadata ext.ThoughtMetadata
if len(m.Metadata) > 0 {
if err := json.Unmarshal(m.Metadata, &metadata); err != nil {
return ext.Thought{}, fmt.Errorf("decode thought metadata: %w", err)
}
}
var projectID *uuid.UUID
if m.ProjectID.Valid {
id := m.ProjectID.UUID()
projectID = &id
}
var archivedAt *time.Time
if m.ArchivedAt.Valid {
t := m.ArchivedAt.Time()
archivedAt = &t
}
return ext.Thought{
ID: m.GUID.UUID(),
Content: m.Content.String(),
Metadata: metadata,
ProjectID: projectID,
ArchivedAt: archivedAt,
CreatedAt: m.CreatedAt.Time(),
UpdatedAt: m.UpdatedAt.Time(),
}, nil
}
func storedFileFromModel(m generatedmodels.ModelPublicStoredFiles) ext.StoredFile {
var thoughtID *uuid.UUID
if m.ThoughtID.Valid {
id := m.ThoughtID.UUID()
thoughtID = &id
}
var projectID *uuid.UUID
if m.ProjectID.Valid {
id := m.ProjectID.UUID()
projectID = &id
}
return ext.StoredFile{
ID: m.GUID.UUID(),
ThoughtID: thoughtID,
ProjectID: projectID,
Name: m.Name.String(),
MediaType: m.MediaType.String(),
Kind: m.Kind.String(),
Encoding: m.Encoding.String(),
SizeBytes: m.SizeBytes,
SHA256: m.Sha256.String(),
Content: m.Content,
CreatedAt: m.CreatedAt.Time(),
UpdatedAt: m.UpdatedAt.Time(),
}
}
func maintenanceTaskFromModel(m generatedmodels.ModelPublicMaintenanceTasks) ext.MaintenanceTask {
var frequencyDays *int
if m.FrequencyDays.Valid {
n := int(m.FrequencyDays.Int64())
frequencyDays = &n
}
var lastCompleted *time.Time
if m.LastCompleted.Valid {
t := m.LastCompleted.Time()
lastCompleted = &t
}
var nextDue *time.Time
if m.NextDue.Valid {
t := m.NextDue.Time()
nextDue = &t
}
return ext.MaintenanceTask{
ID: m.ID.UUID(),
Name: m.Name.String(),
Category: m.Category.String(),
FrequencyDays: frequencyDays,
LastCompleted: lastCompleted,
NextDue: nextDue,
Priority: m.Priority.String(),
Notes: m.Notes.String(),
CreatedAt: m.CreatedAt.Time(),
UpdatedAt: m.UpdatedAt.Time(),
}
}
func maintenanceLogFromModel(m generatedmodels.ModelPublicMaintenanceLogs) ext.MaintenanceLog {
var cost *float64
if m.Cost.Valid {
v := m.Cost.Float64()
cost = &v
}
return ext.MaintenanceLog{
ID: m.ID.UUID(),
TaskID: m.TaskID.UUID(),
CompletedAt: m.CompletedAt.Time(),
PerformedBy: m.PerformedBy.String(),
Cost: cost,
Notes: m.Notes.String(),
NextAction: m.NextAction.String(),
}
}
func householdItemFromModel(m generatedmodels.ModelPublicHouseholdItems) ext.HouseholdItem {
details := map[string]any{}
if len(m.Details) > 0 {
if err := json.Unmarshal(m.Details, &details); err != nil {
details = map[string]any{}
}
}
return ext.HouseholdItem{
ID: m.ID.UUID(),
Name: m.Name.String(),
Category: m.Category.String(),
Location: m.Location.String(),
Details: details,
Notes: m.Notes.String(),
CreatedAt: m.CreatedAt.Time(),
UpdatedAt: m.UpdatedAt.Time(),
}
}
func householdVendorFromModel(m generatedmodels.ModelPublicHouseholdVendors) ext.HouseholdVendor {
var rating *int
if m.Rating.Valid {
v := int(m.Rating.Int64())
rating = &v
}
var lastUsed *time.Time
if m.LastUsed.Valid {
t := m.LastUsed.Time()
lastUsed = &t
}
return ext.HouseholdVendor{
ID: m.ID.UUID(),
Name: m.Name.String(),
ServiceType: m.ServiceType.String(),
Phone: m.Phone.String(),
Email: m.Email.String(),
Website: m.Website.String(),
Notes: m.Notes.String(),
Rating: rating,
LastUsed: lastUsed,
CreatedAt: m.CreatedAt.Time(),
}
}
func familyMemberFromModel(m generatedmodels.ModelPublicFamilyMembers) ext.FamilyMember {
var birthDate *time.Time
if m.BirthDate.Valid {
t := m.BirthDate.Time()
birthDate = &t
}
return ext.FamilyMember{
ID: m.ID.UUID(),
Name: m.Name.String(),
Relationship: m.Relationship.String(),
BirthDate: birthDate,
Notes: m.Notes.String(),
CreatedAt: m.CreatedAt.Time(),
}
}
func activityFromModel(m generatedmodels.ModelPublicActivities, memberName string) ext.Activity {
var familyMemberID *uuid.UUID
if m.FamilyMemberID.Valid {
id := m.FamilyMemberID.UUID()
familyMemberID = &id
}
var startDate *time.Time
if m.StartDate.Valid {
t := m.StartDate.Time()
startDate = &t
}
var endDate *time.Time
if m.EndDate.Valid {
t := m.EndDate.Time()
endDate = &t
}
return ext.Activity{
ID: m.ID.UUID(),
FamilyMemberID: familyMemberID,
MemberName: memberName,
Title: m.Title.String(),
ActivityType: m.ActivityType.String(),
DayOfWeek: m.DayOfWeek.String(),
StartTime: m.StartTime.String(),
EndTime: m.EndTime.String(),
StartDate: startDate,
EndDate: endDate,
Location: m.Location.String(),
Notes: m.Notes.String(),
CreatedAt: m.CreatedAt.Time(),
}
}
func importantDateFromModel(m generatedmodels.ModelPublicImportantDates, memberName string) ext.ImportantDate {
var familyMemberID *uuid.UUID
if m.FamilyMemberID.Valid {
id := m.FamilyMemberID.UUID()
familyMemberID = &id
}
return ext.ImportantDate{
ID: m.ID.UUID(),
FamilyMemberID: familyMemberID,
MemberName: memberName,
Title: m.Title.String(),
DateValue: m.DateValue.Time(),
RecurringYearly: m.RecurringYearly,
ReminderDaysBefore: int(m.ReminderDaysBefore.Int64()),
Notes: m.Notes.String(),
CreatedAt: m.CreatedAt.Time(),
}
}
func professionalContactFromModel(m generatedmodels.ModelPublicProfessionalContacts, tags []string) ext.ProfessionalContact {
var lastContacted *time.Time
if m.LastContacted.Valid {
t := m.LastContacted.Time()
lastContacted = &t
}
var followUpDate *time.Time
if m.FollowUpDate.Valid {
t := m.FollowUpDate.Time()
followUpDate = &t
}
return ext.ProfessionalContact{
ID: m.ID.UUID(),
Name: m.Name.String(),
Company: m.Company.String(),
Title: m.Title.String(),
Email: m.Email.String(),
Phone: m.Phone.String(),
LinkedInURL: m.LinkedinURL.String(),
HowWeMet: m.HowWeMet.String(),
Tags: tags,
Notes: m.Notes.String(),
LastContacted: lastContacted,
FollowUpDate: followUpDate,
CreatedAt: m.CreatedAt.Time(),
UpdatedAt: m.UpdatedAt.Time(),
}
}
func contactInteractionFromModel(m generatedmodels.ModelPublicContactInteractions) ext.ContactInteraction {
return ext.ContactInteraction{
ID: m.ID.UUID(),
ContactID: m.ContactID.UUID(),
InteractionType: m.InteractionType.String(),
OccurredAt: m.OccurredAt.Time(),
Summary: m.Summary.String(),
FollowUpNeeded: m.FollowUpNeeded,
FollowUpNotes: m.FollowUpNotes.String(),
CreatedAt: m.CreatedAt.Time(),
}
}
func opportunityFromModel(m generatedmodels.ModelPublicOpportunities) ext.Opportunity {
var contactID *uuid.UUID
if m.ContactID.Valid {
id := m.ContactID.UUID()
contactID = &id
}
var value *float64
if m.Value.Valid {
v := m.Value.Float64()
value = &v
}
var expectedCloseDate *time.Time
if m.ExpectedCloseDate.Valid {
t := m.ExpectedCloseDate.Time()
expectedCloseDate = &t
}
return ext.Opportunity{
ID: m.ID.UUID(),
ContactID: contactID,
Title: m.Title.String(),
Description: m.Description.String(),
Stage: m.Stage.String(),
Value: value,
ExpectedCloseDate: expectedCloseDate,
Notes: m.Notes.String(),
CreatedAt: m.CreatedAt.Time(),
UpdatedAt: m.UpdatedAt.Time(),
}
}
func recipeFromModel(m generatedmodels.ModelPublicRecipes, tags []string) ext.Recipe {
var prepTimeMinutes *int
if m.PrepTimeMinutes.Valid {
v := int(m.PrepTimeMinutes.Int64())
prepTimeMinutes = &v
}
var cookTimeMinutes *int
if m.CookTimeMinutes.Valid {
v := int(m.CookTimeMinutes.Int64())
cookTimeMinutes = &v
}
var servings *int
if m.Servings.Valid {
v := int(m.Servings.Int64())
servings = &v
}
var rating *int
if m.Rating.Valid {
v := int(m.Rating.Int64())
rating = &v
}
recipe := ext.Recipe{
ID: m.ID.UUID(),
Name: m.Name.String(),
Cuisine: m.Cuisine.String(),
PrepTimeMinutes: prepTimeMinutes,
CookTimeMinutes: cookTimeMinutes,
Servings: servings,
Tags: tags,
Rating: rating,
Notes: m.Notes.String(),
CreatedAt: m.CreatedAt.Time(),
UpdatedAt: m.UpdatedAt.Time(),
}
if err := json.Unmarshal(m.Ingredients, &recipe.Ingredients); err != nil {
recipe.Ingredients = []ext.Ingredient{}
}
if err := json.Unmarshal(m.Instructions, &recipe.Instructions); err != nil {
recipe.Instructions = []string{}
}
return recipe
}
func mealPlanEntryFromModel(m generatedmodels.ModelPublicMealPlans, recipeName string) ext.MealPlanEntry {
var recipeID *uuid.UUID
if m.RecipeID.Valid {
id := m.RecipeID.UUID()
recipeID = &id
}
var servings *int
if m.Servings.Valid {
v := int(m.Servings.Int64())
servings = &v
}
return ext.MealPlanEntry{
ID: m.ID.UUID(),
WeekStart: m.WeekStart.Time(),
DayOfWeek: m.DayOfWeek.String(),
MealType: m.MealType.String(),
RecipeID: recipeID,
RecipeName: recipeName,
CustomMeal: m.CustomMeal.String(),
Servings: servings,
Notes: m.Notes.String(),
CreatedAt: m.CreatedAt.Time(),
}
}
func shoppingListFromModel(m generatedmodels.ModelPublicShoppingLists) ext.ShoppingList {
list := ext.ShoppingList{
ID: m.ID.UUID(),
WeekStart: m.WeekStart.Time(),
Notes: m.Notes.String(),
CreatedAt: m.CreatedAt.Time(),
UpdatedAt: m.UpdatedAt.Time(),
}
if err := json.Unmarshal(m.Items, &list.Items); err != nil {
list.Items = []ext.ShoppingItem{}
}
return list
}
func learningFromModel(m generatedmodels.ModelPublicLearnings, tags []string) ext.Learning {
var projectID *uuid.UUID
if m.ProjectID.Valid {
id := m.ProjectID.UUID()
projectID = &id
}
var relatedThoughtID *uuid.UUID
if m.RelatedThoughtID.Valid {
id := m.RelatedThoughtID.UUID()
relatedThoughtID = &id
}
var relatedSkillID *uuid.UUID
if m.RelatedSkillID.Valid {
id := m.RelatedSkillID.UUID()
relatedSkillID = &id
}
var duplicateOfLearningID *uuid.UUID
if m.DuplicateOfLearningID.Valid {
id := m.DuplicateOfLearningID.UUID()
duplicateOfLearningID = &id
}
var supersedesLearningID *uuid.UUID
if m.SupersedesLearningID.Valid {
id := m.SupersedesLearningID.UUID()
supersedesLearningID = &id
}
var reviewedBy *string
if m.ReviewedBy.Valid {
value := m.ReviewedBy.String()
reviewedBy = &value
}
var reviewedAt *time.Time
if m.ReviewedAt.Valid {
t := m.ReviewedAt.Time()
reviewedAt = &t
}
return ext.Learning{
ID: m.ID.UUID(),
Summary: m.Summary.String(),
Details: m.Details.String(),
Category: m.Category.String(),
Area: m.Area.String(),
Status: ext.LearningStatus(m.Status.String()),
Priority: ext.LearningPriority(m.Priority.String()),
Confidence: ext.LearningEvidenceLevel(m.Confidence.String()),
ActionRequired: m.ActionRequired,
SourceType: m.SourceType.String(),
SourceRef: m.SourceRef.String(),
ProjectID: projectID,
RelatedThoughtID: relatedThoughtID,
RelatedSkillID: relatedSkillID,
ReviewedBy: reviewedBy,
ReviewedAt: reviewedAt,
DuplicateOfLearningID: duplicateOfLearningID,
SupersedesLearningID: supersedesLearningID,
Tags: tags,
CreatedAt: m.CreatedAt.Time(),
UpdatedAt: m.UpdatedAt.Time(),
}
}

View File

@@ -8,6 +8,7 @@ import (
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
thoughttypes "git.warky.dev/wdevs/amcs/internal/types"
)
@@ -18,11 +19,11 @@ func (db *DB) CreateProject(ctx context.Context, name, description string) (thou
returning guid, name, description, created_at, last_active_at
`, name, description)
var project thoughttypes.Project
if err := row.Scan(&project.ID, &project.Name, &project.Description, &project.CreatedAt, &project.LastActiveAt); err != nil {
var model generatedmodels.ModelPublicProjects
if err := row.Scan(&model.GUID, &model.Name, &model.Description, &model.CreatedAt, &model.LastActiveAt); err != nil {
return thoughttypes.Project{}, fmt.Errorf("create project: %w", err)
}
return project, nil
return projectFromModel(model), nil
}
func (db *DB) GetProject(ctx context.Context, nameOrID string) (thoughttypes.Project, error) {
@@ -62,14 +63,14 @@ func (db *DB) getProjectByName(ctx context.Context, name string) (thoughttypes.P
}
func scanProject(row pgx.Row) (thoughttypes.Project, error) {
var project thoughttypes.Project
if err := row.Scan(&project.ID, &project.Name, &project.Description, &project.CreatedAt, &project.LastActiveAt); err != nil {
var model generatedmodels.ModelPublicProjects
if err := row.Scan(&model.GUID, &model.Name, &model.Description, &model.CreatedAt, &model.LastActiveAt); err != nil {
if err == pgx.ErrNoRows {
return thoughttypes.Project{}, err
}
return thoughttypes.Project{}, fmt.Errorf("get project: %w", err)
}
return project, nil
return projectFromModel(model), nil
}
func (db *DB) ListProjects(ctx context.Context) ([]thoughttypes.ProjectSummary, error) {
@@ -87,11 +88,15 @@ func (db *DB) ListProjects(ctx context.Context) ([]thoughttypes.ProjectSummary,
projects := make([]thoughttypes.ProjectSummary, 0)
for rows.Next() {
var project thoughttypes.ProjectSummary
if err := rows.Scan(&project.ID, &project.Name, &project.Description, &project.CreatedAt, &project.LastActiveAt, &project.ThoughtCount); err != nil {
var model generatedmodels.ModelPublicProjects
var thoughtCount int
if err := rows.Scan(&model.GUID, &model.Name, &model.Description, &model.CreatedAt, &model.LastActiveAt, &thoughtCount); err != nil {
return nil, fmt.Errorf("scan project summary: %w", err)
}
projects = append(projects, project)
projects = append(projects, thoughttypes.ProjectSummary{
Project: projectFromModel(model),
ThoughtCount: thoughtCount,
})
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("iterate projects: %w", err)

View File

@@ -7,6 +7,7 @@ import (
"github.com/google/uuid"
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
ext "git.warky.dev/wdevs/amcs/internal/types"
)
@@ -23,9 +24,13 @@ func (db *DB) AddSkill(ctx context.Context, skill ext.AgentSkill) (ext.AgentSkil
`, skill.Name, skill.Description, skill.Content, skill.Tags)
created := skill
if err := row.Scan(&created.ID, &created.CreatedAt, &created.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicAgentSkills
if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
return ext.AgentSkill{}, fmt.Errorf("insert agent skill: %w", err)
}
created.ID = model.ID.UUID()
created.CreatedAt = model.CreatedAt.Time()
created.UpdatedAt = model.UpdatedAt.Time()
return created, nil
}
@@ -41,7 +46,7 @@ func (db *DB) RemoveSkill(ctx context.Context, id uuid.UUID) error {
}
func (db *DB) ListSkills(ctx context.Context, tag string) ([]ext.AgentSkill, error) {
q := `select id, name, description, content, tags, created_at, updated_at from agent_skills`
q := `select id, name, description, content, tags::text[], created_at, updated_at from agent_skills`
args := []any{}
if t := strings.TrimSpace(tag); t != "" {
args = append(args, t)
@@ -57,12 +62,20 @@ func (db *DB) ListSkills(ctx context.Context, tag string) ([]ext.AgentSkill, err
var skills []ext.AgentSkill
for rows.Next() {
var s ext.AgentSkill
var desc *string
if err := rows.Scan(&s.ID, &s.Name, &desc, &s.Content, &s.Tags, &s.CreatedAt, &s.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicAgentSkills
var tags []string
if err := rows.Scan(&model.ID, &model.Name, &model.Description, &model.Content, &tags, &model.CreatedAt, &model.UpdatedAt); err != nil {
return nil, fmt.Errorf("scan agent skill: %w", err)
}
s.Description = strVal(desc)
s := ext.AgentSkill{
ID: model.ID.UUID(),
Name: model.Name.String(),
Description: model.Description.String(),
Content: model.Content.String(),
Tags: tags,
CreatedAt: model.CreatedAt.Time(),
UpdatedAt: model.UpdatedAt.Time(),
}
if s.Tags == nil {
s.Tags = []string{}
}
@@ -73,16 +86,24 @@ func (db *DB) ListSkills(ctx context.Context, tag string) ([]ext.AgentSkill, err
func (db *DB) GetSkill(ctx context.Context, id uuid.UUID) (ext.AgentSkill, error) {
row := db.pool.QueryRow(ctx, `
select id, name, description, content, tags, created_at, updated_at
select id, name, description, content, tags::text[], created_at, updated_at
from agent_skills where id = $1
`, id)
var s ext.AgentSkill
var desc *string
if err := row.Scan(&s.ID, &s.Name, &desc, &s.Content, &s.Tags, &s.CreatedAt, &s.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicAgentSkills
var tags []string
if err := row.Scan(&model.ID, &model.Name, &model.Description, &model.Content, &tags, &model.CreatedAt, &model.UpdatedAt); err != nil {
return ext.AgentSkill{}, fmt.Errorf("get agent skill: %w", err)
}
s.Description = strVal(desc)
s := ext.AgentSkill{
ID: model.ID.UUID(),
Name: model.Name.String(),
Description: model.Description.String(),
Content: model.Content.String(),
Tags: tags,
CreatedAt: model.CreatedAt.Time(),
UpdatedAt: model.UpdatedAt.Time(),
}
if s.Tags == nil {
s.Tags = []string{}
}
@@ -105,9 +126,13 @@ func (db *DB) AddGuardrail(ctx context.Context, g ext.AgentGuardrail) (ext.Agent
`, g.Name, g.Description, g.Content, g.Severity, g.Tags)
created := g
if err := row.Scan(&created.ID, &created.CreatedAt, &created.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicAgentGuardrails
if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
return ext.AgentGuardrail{}, fmt.Errorf("insert agent guardrail: %w", err)
}
created.ID = model.ID.UUID()
created.CreatedAt = model.CreatedAt.Time()
created.UpdatedAt = model.UpdatedAt.Time()
return created, nil
}
@@ -135,7 +160,7 @@ func (db *DB) ListGuardrails(ctx context.Context, tag, severity string) ([]ext.A
conditions = append(conditions, fmt.Sprintf("severity = $%d", len(args)))
}
q := `select id, name, description, content, severity, tags, created_at, updated_at from agent_guardrails`
q := `select id, name, description, content, severity, tags::text[], created_at, updated_at from agent_guardrails`
if len(conditions) > 0 {
q += " where " + strings.Join(conditions, " and ")
}
@@ -149,12 +174,21 @@ func (db *DB) ListGuardrails(ctx context.Context, tag, severity string) ([]ext.A
var guardrails []ext.AgentGuardrail
for rows.Next() {
var g ext.AgentGuardrail
var desc *string
if err := rows.Scan(&g.ID, &g.Name, &desc, &g.Content, &g.Severity, &g.Tags, &g.CreatedAt, &g.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicAgentGuardrails
var tags []string
if err := rows.Scan(&model.ID, &model.Name, &model.Description, &model.Content, &model.Severity, &tags, &model.CreatedAt, &model.UpdatedAt); err != nil {
return nil, fmt.Errorf("scan agent guardrail: %w", err)
}
g.Description = strVal(desc)
g := ext.AgentGuardrail{
ID: model.ID.UUID(),
Name: model.Name.String(),
Description: model.Description.String(),
Content: model.Content.String(),
Severity: model.Severity.String(),
Tags: tags,
CreatedAt: model.CreatedAt.Time(),
UpdatedAt: model.UpdatedAt.Time(),
}
if g.Tags == nil {
g.Tags = []string{}
}
@@ -165,16 +199,25 @@ func (db *DB) ListGuardrails(ctx context.Context, tag, severity string) ([]ext.A
func (db *DB) GetGuardrail(ctx context.Context, id uuid.UUID) (ext.AgentGuardrail, error) {
row := db.pool.QueryRow(ctx, `
select id, name, description, content, severity, tags, created_at, updated_at
select id, name, description, content, severity, tags::text[], created_at, updated_at
from agent_guardrails where id = $1
`, id)
var g ext.AgentGuardrail
var desc *string
if err := row.Scan(&g.ID, &g.Name, &desc, &g.Content, &g.Severity, &g.Tags, &g.CreatedAt, &g.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicAgentGuardrails
var tags []string
if err := row.Scan(&model.ID, &model.Name, &model.Description, &model.Content, &model.Severity, &tags, &model.CreatedAt, &model.UpdatedAt); err != nil {
return ext.AgentGuardrail{}, fmt.Errorf("get agent guardrail: %w", err)
}
g.Description = strVal(desc)
g := ext.AgentGuardrail{
ID: model.ID.UUID(),
Name: model.Name.String(),
Description: model.Description.String(),
Content: model.Content.String(),
Severity: model.Severity.String(),
Tags: tags,
CreatedAt: model.CreatedAt.Time(),
UpdatedAt: model.UpdatedAt.Time(),
}
if g.Tags == nil {
g.Tags = []string{}
}
@@ -210,7 +253,7 @@ func (db *DB) RemoveProjectSkill(ctx context.Context, projectID, skillID uuid.UU
func (db *DB) ListProjectSkills(ctx context.Context, projectID uuid.UUID) ([]ext.AgentSkill, error) {
rows, err := db.pool.Query(ctx, `
select s.id, s.name, s.description, s.content, s.tags, s.created_at, s.updated_at
select s.id, s.name, s.description, s.content, s.tags::text[], s.created_at, s.updated_at
from agent_skills s
join project_skills ps on ps.skill_id = s.id
where ps.project_id = $1
@@ -223,12 +266,20 @@ func (db *DB) ListProjectSkills(ctx context.Context, projectID uuid.UUID) ([]ext
var skills []ext.AgentSkill
for rows.Next() {
var s ext.AgentSkill
var desc *string
if err := rows.Scan(&s.ID, &s.Name, &desc, &s.Content, &s.Tags, &s.CreatedAt, &s.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicAgentSkills
var tags []string
if err := rows.Scan(&model.ID, &model.Name, &model.Description, &model.Content, &tags, &model.CreatedAt, &model.UpdatedAt); err != nil {
return nil, fmt.Errorf("scan project skill: %w", err)
}
s.Description = strVal(desc)
s := ext.AgentSkill{
ID: model.ID.UUID(),
Name: model.Name.String(),
Description: model.Description.String(),
Content: model.Content.String(),
Tags: tags,
CreatedAt: model.CreatedAt.Time(),
UpdatedAt: model.UpdatedAt.Time(),
}
if s.Tags == nil {
s.Tags = []string{}
}
@@ -266,7 +317,7 @@ func (db *DB) RemoveProjectGuardrail(ctx context.Context, projectID, guardrailID
func (db *DB) ListProjectGuardrails(ctx context.Context, projectID uuid.UUID) ([]ext.AgentGuardrail, error) {
rows, err := db.pool.Query(ctx, `
select g.id, g.name, g.description, g.content, g.severity, g.tags, g.created_at, g.updated_at
select g.id, g.name, g.description, g.content, g.severity, g.tags::text[], g.created_at, g.updated_at
from agent_guardrails g
join project_guardrails pg on pg.guardrail_id = g.id
where pg.project_id = $1
@@ -279,12 +330,21 @@ func (db *DB) ListProjectGuardrails(ctx context.Context, projectID uuid.UUID) ([
var guardrails []ext.AgentGuardrail
for rows.Next() {
var g ext.AgentGuardrail
var desc *string
if err := rows.Scan(&g.ID, &g.Name, &desc, &g.Content, &g.Severity, &g.Tags, &g.CreatedAt, &g.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicAgentGuardrails
var tags []string
if err := rows.Scan(&model.ID, &model.Name, &model.Description, &model.Content, &model.Severity, &tags, &model.CreatedAt, &model.UpdatedAt); err != nil {
return nil, fmt.Errorf("scan project guardrail: %w", err)
}
g.Description = strVal(desc)
g := ext.AgentGuardrail{
ID: model.ID.UUID(),
Name: model.Name.String(),
Description: model.Description.String(),
Content: model.Content.String(),
Severity: model.Severity.String(),
Tags: tags,
CreatedAt: model.CreatedAt.Time(),
UpdatedAt: model.UpdatedAt.Time(),
}
if g.Tags == nil {
g.Tags = []string{}
}

View File

@@ -12,6 +12,7 @@ import (
"github.com/jackc/pgx/v5"
"github.com/pgvector/pgvector-go"
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
thoughttypes "git.warky.dev/wdevs/amcs/internal/types"
)
@@ -149,13 +150,13 @@ func (db *DB) ListThoughts(ctx context.Context, filter thoughttypes.ListFilter)
thoughts := make([]thoughttypes.Thought, 0, filter.Limit)
for rows.Next() {
var thought thoughttypes.Thought
var metadataBytes []byte
if err := rows.Scan(&thought.ID, &thought.Content, &metadataBytes, &thought.ProjectID, &thought.ArchivedAt, &thought.CreatedAt, &thought.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicThoughts
if err := rows.Scan(&model.GUID, &model.Content, &model.Metadata, &model.ProjectID, &model.ArchivedAt, &model.CreatedAt, &model.UpdatedAt); err != nil {
return nil, fmt.Errorf("scan listed thought: %w", err)
}
if err := json.Unmarshal(metadataBytes, &thought.Metadata); err != nil {
return nil, fmt.Errorf("decode listed metadata: %w", err)
thought, err := thoughtFromModel(model)
if err != nil {
return nil, fmt.Errorf("map listed thought: %w", err)
}
thoughts = append(thoughts, thought)
}
@@ -222,17 +223,17 @@ func (db *DB) GetThought(ctx context.Context, id uuid.UUID) (thoughttypes.Though
where guid = $1
`, id)
var thought thoughttypes.Thought
var metadataBytes []byte
if err := row.Scan(&thought.ID, &thought.Content, &metadataBytes, &thought.ProjectID, &thought.ArchivedAt, &thought.CreatedAt, &thought.UpdatedAt); err != nil {
var model generatedmodels.ModelPublicThoughts
if err := row.Scan(&model.GUID, &model.Content, &model.Metadata, &model.ProjectID, &model.ArchivedAt, &model.CreatedAt, &model.UpdatedAt); err != nil {
if err == pgx.ErrNoRows {
return thoughttypes.Thought{}, err
}
return thoughttypes.Thought{}, fmt.Errorf("get thought: %w", err)
}
if err := json.Unmarshal(metadataBytes, &thought.Metadata); err != nil {
return thoughttypes.Thought{}, fmt.Errorf("decode thought metadata: %w", err)
thought, err := thoughtFromModel(model)
if err != nil {
return thoughttypes.Thought{}, fmt.Errorf("map thought: %w", err)
}
return thought, nil

View File

@@ -3,6 +3,8 @@ package store
import (
"context"
"fmt"
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
)
func (db *DB) UpsertToolAnnotation(ctx context.Context, toolName, notes string) error {
@@ -28,11 +30,11 @@ func (db *DB) GetToolAnnotations(ctx context.Context) (map[string]string, error)
annotations := make(map[string]string)
for rows.Next() {
var toolName, notes string
if err := rows.Scan(&toolName, &notes); err != nil {
var model generatedmodels.ModelPublicToolAnnotations
if err := rows.Scan(&model.ToolName, &model.Notes); err != nil {
return nil, fmt.Errorf("scan tool annotation: %w", err)
}
annotations[toolName] = notes
annotations[model.ToolName.String()] = model.Notes.String()
}
return annotations, rows.Err()
}