c179e014ad
CI / build-and-test (push) Failing after 1m52s
* Introduce project_personas table with foreign keys to projects and agent_personas * Add project_skills table with foreign key to projects and agent_skills * Include override boolean field in agent_persona_skills and project_skills * Update schema and migration files to reflect new tables and fields * Enhance CORS handling to reflect request origin
100 lines
3.3 KiB
Go
100 lines
3.3 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
|
|
ext "git.warky.dev/wdevs/amcs/internal/types"
|
|
)
|
|
|
|
func (db *DB) AddProjectPersona(ctx context.Context, projectID, personaID int64, isDefault bool) error {
|
|
tx, err := db.pool.Begin(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("begin add project persona: %w", err)
|
|
}
|
|
defer func() { _ = tx.Rollback(ctx) }()
|
|
|
|
if _, err := tx.Exec(ctx, `select pg_advisory_xact_lock($1)`, projectID); err != nil {
|
|
return fmt.Errorf("lock project persona defaults: %w", err)
|
|
}
|
|
if isDefault {
|
|
if _, err := tx.Exec(ctx, `update project_personas set is_default = false where project_id = $1`, projectID); err != nil {
|
|
return fmt.Errorf("clear default project persona: %w", err)
|
|
}
|
|
}
|
|
if _, err := tx.Exec(ctx, `
|
|
insert into project_personas (project_id, persona_id, is_default)
|
|
values ($1, $2, $3)
|
|
on conflict (project_id, persona_id) do update set is_default = excluded.is_default
|
|
`, projectID, personaID, isDefault); err != nil {
|
|
return fmt.Errorf("add project persona: %w", err)
|
|
}
|
|
if err := tx.Commit(ctx); err != nil {
|
|
return fmt.Errorf("commit add project persona: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (db *DB) RemoveProjectPersona(ctx context.Context, projectID, personaID int64) error {
|
|
tag, err := db.pool.Exec(ctx, `delete from project_personas where project_id = $1 and persona_id = $2`, projectID, personaID)
|
|
if err != nil {
|
|
return fmt.Errorf("remove project persona: %w", err)
|
|
}
|
|
if tag.RowsAffected() == 0 {
|
|
return fmt.Errorf("project persona link not found")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (db *DB) ListProjectPersonas(ctx context.Context, projectID int64) ([]ext.ProjectPersona, error) {
|
|
rows, err := db.pool.Query(ctx, `
|
|
select p.id, p.guid, p.name, p.description, p.summary, p.detail,
|
|
p.compiled_summary, p.compiled_detail, p.compiled_at, p.tags::text[],
|
|
p.created_at, p.updated_at, pp.is_default
|
|
from agent_personas p
|
|
join project_personas pp on pp.persona_id = p.id
|
|
where pp.project_id = $1
|
|
order by pp.is_default desc, p.name
|
|
`, projectID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("list project personas: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
var result []ext.ProjectPersona
|
|
for rows.Next() {
|
|
var item ext.ProjectPersona
|
|
var tags []string
|
|
if err := rows.Scan(&item.Persona.ID, &item.Persona.GUID, &item.Persona.Name,
|
|
&item.Persona.Description, &item.Persona.Summary, &item.Persona.Detail,
|
|
&item.Persona.CompiledSummary, &item.Persona.CompiledDetail, &item.Persona.CompiledAt,
|
|
&tags, &item.Persona.CreatedAt, &item.Persona.UpdatedAt, &item.IsDefault); err != nil {
|
|
return nil, fmt.Errorf("scan project persona: %w", err)
|
|
}
|
|
item.Persona.Tags = nilToEmptyStrings(tags)
|
|
result = append(result, item)
|
|
}
|
|
return result, rows.Err()
|
|
}
|
|
|
|
func (db *DB) GetDefaultProjectPersona(ctx context.Context, projectID int64) (*ext.Persona, error) {
|
|
row := db.pool.QueryRow(ctx, `
|
|
select p.id, p.guid, p.name, p.description, p.summary, p.detail,
|
|
p.compiled_summary, p.compiled_detail, p.compiled_at, p.tags::text[],
|
|
p.created_at, p.updated_at
|
|
from agent_personas p
|
|
join project_personas pp on pp.persona_id = p.id
|
|
where pp.project_id = $1 and pp.is_default
|
|
`, projectID)
|
|
persona, err := scanPersona(row)
|
|
if err == pgx.ErrNoRows {
|
|
return nil, nil
|
|
}
|
|
if err != nil {
|
|
return nil, fmt.Errorf("get default project persona: %w", err)
|
|
}
|
|
return &persona, nil
|
|
}
|