2026-10-15 18:33:18 -07:00
package store
import (
"context"
"database/sql"
"encoding/json"
2026-10-18 08:48:57 -07:00
"errors"
2026-10-15 18:33:18 -07:00
"time"
)
type TaskInput struct {
ID int64
TaskID string
2026-10-18 08:48:57 -07:00
Member string
2026-10-15 18:33:18 -07:00
Actor string
Text string
Images [] string
CreatedAt time . Time
}
2026-10-17 15:33:59 -07:00
func ( s * Store ) AddTaskInput ( ctx context . Context , in TaskInput , projectID , sessionID string ) error {
2026-10-15 18:33:18 -07:00
images , err := json . Marshal ( append ([] string {}, in . Images ... ))
if err != nil {
return err
}
2026-10-17 15:33:59 -07:00
payload := map [ string ] any { "text" : in . Text }
if len ( in . Images ) > 0 {
payload [ "images" ] = in . Images
}
2026-10-15 18:33:18 -07:00
return s . write ( ctx , func ( tx * sql . Tx , emit emitFunc ) error {
2026-10-18 08:48:57 -07:00
res , err := tx . ExecContext ( ctx , `INSERT INTO task_inputs (task_id, member, actor, text, images, created_at) VALUES (?, ?, ?, ?, ?, ?)` ,
in . TaskID , in . Member , in . Actor , in . Text , string ( images ), now ())
2026-10-17 15:33:59 -07:00
if err != nil {
return err
}
2026-10-17 15:45:27 -07:00
payload [ "id" ], err = res . LastInsertId ()
if err != nil {
return err
}
2026-10-17 15:33:59 -07:00
return emit ( sessionEvent ( "user.queued" , projectID , in . TaskID , "" , sessionID , in . Actor , payload ))
2026-10-15 18:33:18 -07:00
})
}
2026-10-18 08:48:57 -07:00
func ( s * Store ) WithdrawTaskInput ( ctx context . Context , taskID string , id int64 , projectID , actor string ) ( string , error ) {
sessionID := ""
err := s . write ( ctx , func ( tx * sql . Tx , emit emitFunc ) error {
member := ""
err := tx . QueryRowContext ( ctx , `DELETE FROM task_inputs WHERE id = ? AND task_id = ? RETURNING member` , id , taskID ). Scan ( & member )
if errors . Is ( err , sql . ErrNoRows ) {
return ErrNotFound
}
2026-10-17 15:45:27 -07:00
if err != nil {
return err
}
2026-10-18 08:48:57 -07:00
err = tx . QueryRowContext ( ctx , `SELECT id FROM agent_sessions WHERE task_id = ? AND member = ? AND role = 'implementer' ORDER BY created_at DESC LIMIT 1` , taskID , member ). Scan ( & sessionID )
2026-10-17 15:45:27 -07:00
if err != nil {
return err
}
return emit ( sessionEvent ( "user.unqueued" , projectID , taskID , "" , sessionID , actor , map [ string ] any { "id" : id }))
})
2026-10-18 08:48:57 -07:00
return sessionID , err
2026-10-17 15:45:27 -07:00
}
2026-10-18 08:48:57 -07:00
func ( s * Store ) TaskInputs ( ctx context . Context , taskID , member string ) ([] TaskInput , error ) {
rows , err := s . db . QueryContext ( ctx , `SELECT id, task_id, member, actor, text, images, created_at FROM task_inputs WHERE task_id = ? AND member = ? ORDER BY id` , taskID , member )
2026-10-15 18:33:18 -07:00
if err != nil {
return nil , err
}
defer rows . Close ()
inputs := [] TaskInput {}
for rows . Next () {
in := TaskInput {}
images := ""
createdAt := ""
2026-10-18 08:48:57 -07:00
err = rows . Scan ( & in . ID , & in . TaskID , & in . Member , & in . Actor , & in . Text , & images , & createdAt )
2026-10-15 18:33:18 -07:00
if err != nil {
return nil , err
}
err = json . Unmarshal ([] byte ( images ), & in . Images )
if err != nil {
return nil , err
}
in . CreatedAt , err = parseTime ( createdAt )
if err != nil {
return nil , err
}
inputs = append ( inputs , in )
}
return inputs , rows . Err ()
}
2026-10-16 14:18:40 -07:00
func ( s * Store ) RestoreTaskInputs ( ctx context . Context , inputs [] TaskInput ) error {
return s . write ( ctx , func ( tx * sql . Tx , emit emitFunc ) error {
for _ , in := range inputs {
images , err := json . Marshal ( append ([] string {}, in . Images ... ))
if err != nil {
return err
}
2026-10-18 08:48:57 -07:00
_ , err = tx . ExecContext ( ctx , `INSERT INTO task_inputs (id, task_id, member, actor, text, images, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)` ,
in . ID , in . TaskID , in . Member , in . Actor , in . Text , string ( images ), formatTime ( in . CreatedAt ))
2026-10-16 14:18:40 -07:00
if err != nil {
return err
}
}
return nil
})
}
2026-10-15 18:33:18 -07:00
func ( s * Store ) DeleteTaskInputs ( ctx context . Context , ids [] int64 ) error {
return s . write ( ctx , func ( tx * sql . Tx , emit emitFunc ) error {
for _ , id := range ids {
_ , err := tx . ExecContext ( ctx , `DELETE FROM task_inputs WHERE id = ?` , id )
if err != nil {
return err
}
}
return nil
})
}