Mark unread turn summaries in the switcher and Project rows

This commit is contained in:
Ian Gulliver
2026-10-16 11:08:57 -07:00
parent ec169583ff
commit 34db128afe
24 changed files with 755 additions and 239 deletions
+268 -204
View File
@@ -1003,6 +1003,12 @@ type Status struct {
Zombies []Zombie `json:"zombies"`
}
// SummaryRead defines model for SummaryRead.
type SummaryRead struct {
// Seq The seq of the turn.ended event whose summary was shown.
Seq int64 `json:"seq"`
}
// Task defines model for Task.
type Task struct {
BaseRef string `json:"base_ref"`
@@ -1051,7 +1057,10 @@ type Task struct {
// Reviewing Whether a review of one of the task's snapshots is running.
Reviewing bool `json:"reviewing"`
Status TaskStatus `json:"status"`
Title string `json:"title"`
// SummarySeq The seq of the task's latest turn.ended event with summary: true; 0 when it has none.
SummarySeq int64 `json:"summary_seq"`
Title string `json:"title"`
// TodoItem The title of the TODO.md item the task was started from; absent for other tasks.
TodoItem *string `json:"todo_item,omitempty"`
@@ -1346,6 +1355,9 @@ type MergeTaskJSONRequestBody MergeTaskJSONBody
// CreateSessionJSONRequestBody defines body for CreateSession for application/json ContentType.
type CreateSessionJSONRequestBody = SessionCreate
// MarkSummaryReadJSONRequestBody defines body for MarkSummaryRead for application/json ContentType.
type MarkSummaryReadJSONRequestBody = SummaryRead
// ServerInterface represents all server handlers.
type ServerInterface interface {
@@ -1400,6 +1412,9 @@ type ServerInterface interface {
// (PUT /api/me/pane-focus)
SetPaneFocus(w http.ResponseWriter, r *http.Request)
// (GET /api/me/summary-reads)
GetSummaryReads(w http.ResponseWriter, r *http.Request)
// (GET /api/projects)
ListProjects(w http.ResponseWriter, r *http.Request)
@@ -1487,6 +1502,9 @@ type ServerInterface interface {
// (POST /api/tasks/{taskId}/snapshots/{n}/fork)
ForkSnapshot(w http.ResponseWriter, r *http.Request, taskId string, n int)
// (PUT /api/tasks/{taskId}/summary-read)
MarkSummaryRead(w http.ResponseWriter, r *http.Request, taskId string)
// (GET /api/tasks/{taskId}/terminal)
GetTaskTerminal(w http.ResponseWriter, r *http.Request, taskId string, params GetTaskTerminalParams)
@@ -1906,6 +1924,20 @@ func (siw *ServerInterfaceWrapper) SetPaneFocus(w http.ResponseWriter, r *http.R
handler.ServeHTTP(w, r)
}
// GetSummaryReads operation middleware
func (siw *ServerInterfaceWrapper) GetSummaryReads(w http.ResponseWriter, r *http.Request) {
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
siw.Handler.GetSummaryReads(w, r)
}))
for _, middleware := range siw.HandlerMiddlewares {
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
}
// ListProjects operation middleware
func (siw *ServerInterfaceWrapper) ListProjects(w http.ResponseWriter, r *http.Request) {
@@ -2828,6 +2860,32 @@ func (siw *ServerInterfaceWrapper) ForkSnapshot(w http.ResponseWriter, r *http.R
handler.ServeHTTP(w, r)
}
// MarkSummaryRead operation middleware
func (siw *ServerInterfaceWrapper) MarkSummaryRead(w http.ResponseWriter, r *http.Request) {
var err error
_ = err
// ------------- Path parameter "taskId" -------------
var taskId string
err = runtime.BindStyledParameterWithOptions("simple", "taskId", r.PathValue("taskId"), &taskId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "", ValueIsUnescaped: true})
if err != nil {
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "taskId", Err: err})
return
}
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
siw.Handler.MarkSummaryRead(w, r, taskId)
}))
for _, middleware := range siw.HandlerMiddlewares {
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
}
// GetTaskTerminal operation middleware
func (siw *ServerInterfaceWrapper) GetTaskTerminal(w http.ResponseWriter, r *http.Request) {
@@ -3182,6 +3240,7 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H
m.HandleFunc(http.MethodDelete+" "+options.BaseURL+"/api/me/lead/notes/{noteId}", wrapper.DeleteLeadNote)
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/me/focus", wrapper.GetFocus)
m.HandleFunc(http.MethodPut+" "+options.BaseURL+"/api/me/focus", wrapper.SetFocus)
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/me/summary-reads", wrapper.GetSummaryReads)
m.HandleFunc(http.MethodPut+" "+options.BaseURL+"/api/me/pane-focus", wrapper.SetPaneFocus)
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/projects", wrapper.ListProjects)
m.HandleFunc(http.MethodPost+" "+options.BaseURL+"/api/projects", wrapper.CreateProject)
@@ -3192,6 +3251,7 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H
m.HandleFunc(http.MethodPost+" "+options.BaseURL+"/api/projects/{projectId}/todo/tasks", wrapper.StartTodoItem)
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/tasks/{taskId}", wrapper.GetTask)
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/tasks/{taskId}/workflow", wrapper.GetTaskWorkflow)
m.HandleFunc(http.MethodPut+" "+options.BaseURL+"/api/tasks/{taskId}/summary-read", wrapper.MarkSummaryRead)
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/tasks/{taskId}/workflow/run", wrapper.GetWorkflowRun)
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/tasks/{taskId}/unmerged", wrapper.GetUnmerged)
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/tasks/{taskId}/co-authors", wrapper.GetCoAuthors)
@@ -3236,209 +3296,213 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H
// const string: with thousands of chunks the chained `+` fold is several
// times slower for the Go compiler than parsing a slice literal.
var swaggerSpec = []string{
"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",
}
// decodeSpec returns the embedded OpenAPI spec as raw JSON bytes,
+26
View File
@@ -99,6 +99,32 @@ func (s *Server) SetFocus(w http.ResponseWriter, r *http.Request) {
writeJSON(w, http.StatusOK, f)
}
func (s *Server) GetSummaryReads(w http.ResponseWriter, r *http.Request) {
reads, err := s.store.SummaryReads(r.Context(), actor(r))
if err != nil {
writeStoreError(w, err)
return
}
writeJSON(w, http.StatusOK, reads)
}
func (s *Server) MarkSummaryRead(w http.ResponseWriter, r *http.Request, taskId string) {
body := api.SummaryRead{}
if !readJSON(w, r, &body) {
return
}
if body.Seq <= 0 {
writeError(w, http.StatusBadRequest, errors.New("seq must be positive"))
return
}
err := s.store.MarkSummaryRead(r.Context(), actor(r), taskId, body.Seq)
if err != nil {
writeStoreError(w, err)
return
}
w.WriteHeader(http.StatusNoContent)
}
func (s *Server) SetPaneFocus(w http.ResponseWriter, r *http.Request) {
p := api.PaneFocus{}
if !readJSON(w, r, &p) {
+10 -2
View File
@@ -438,6 +438,14 @@ CREATE TABLE lead_notes (
updated_at TEXT NOT NULL
);
CREATE INDEX lead_notes_owner ON lead_notes(owner, created_at);
`}, {"add-summary-reads", `
CREATE INDEX events_summary ON events(task_id, seq) WHERE kind = 'turn.ended' AND json_extract(payload, '$.summary') = 1;
CREATE TABLE summary_reads (
login TEXT NOT NULL REFERENCES users(login),
task_id TEXT NOT NULL REFERENCES tasks(id),
seq INTEGER NOT NULL,
PRIMARY KEY (login, task_id)
);
`}}
const (
@@ -1526,7 +1534,7 @@ func (s *Store) write(ctx context.Context, fn func(tx *sql.Tx, emit emitFunc) er
const projectColumns = `id, name, repo_path, default_branch, remote, created_by, created_at`
const taskColumns = `id, project_id, title, merge_title, branch, worktree_path, base_ref, port_base, color, status, created_by, created_at, closed_at, merge_commit, todo_item, forked_from, forked_at, merge_queued_at, workflow_name, workflow_run, workflow_stage, parent_task_id, parent_merge_by, EXISTS (SELECT 1 FROM reviews WHERE reviews.task_id = tasks.id AND reviews.state = 'running'), merging_by != '', discard_state != '' AND status = 'active'`
const taskColumns = `id, project_id, title, merge_title, branch, worktree_path, base_ref, port_base, color, status, created_by, created_at, closed_at, merge_commit, todo_item, forked_from, forked_at, merge_queued_at, workflow_name, workflow_run, workflow_stage, parent_task_id, parent_merge_by, EXISTS (SELECT 1 FROM reviews WHERE reviews.task_id = tasks.id AND reviews.state = 'running'), merging_by != '', discard_state != '' AND status = 'active', (SELECT coalesce(max(seq), 0) FROM events WHERE events.task_id = tasks.id AND kind = 'turn.ended' AND json_extract(payload, '$.summary') = 1)`
const sessionColumns = `id, coalesce(task_id, ''), owner, vendor, model, vendor_session_id, state, role, created_by, created_at, forked_from, forked_at`
@@ -1560,7 +1568,7 @@ func scanTask(row scanner) (api.Task, error) {
workflowStage := ""
parentTaskID := ""
parentMergeBy := ""
err := row.Scan(&t.Id, &t.ProjectId, &t.Title, &t.MergeTitle, &t.Branch, &t.WorktreePath, &t.BaseRef, &t.PortBase, &t.Color, &status, &t.CreatedBy, &createdAt, &closedAt, &mergeCommit, &todoItem, &forkedFrom, &forkedAt, &mergeQueuedAt, &workflowName, &workflowRun, &workflowStage, &parentTaskID, &parentMergeBy, &t.Reviewing, &t.Merging, &t.Discarding)
err := row.Scan(&t.Id, &t.ProjectId, &t.Title, &t.MergeTitle, &t.Branch, &t.WorktreePath, &t.BaseRef, &t.PortBase, &t.Color, &status, &t.CreatedBy, &createdAt, &closedAt, &mergeCommit, &todoItem, &forkedFrom, &forkedAt, &mergeQueuedAt, &workflowName, &workflowRun, &workflowStage, &parentTaskID, &parentMergeBy, &t.Reviewing, &t.Merging, &t.Discarding, &t.SummarySeq)
if err != nil {
return t, err
}
+61
View File
@@ -0,0 +1,61 @@
package store
import (
"context"
"database/sql"
"errors"
"fmt"
"g.fc.run/misc/byre/internal/api"
)
func (s *Store) SummaryReads(ctx context.Context, login string) (map[string]int64, error) {
rows, err := s.db.QueryContext(ctx, `
SELECT summary_reads.task_id, summary_reads.seq FROM summary_reads
JOIN tasks ON tasks.id = summary_reads.task_id
WHERE summary_reads.login = ? AND tasks.status = ?
`, login, string(api.TaskStatusActive))
if err != nil {
return nil, err
}
defer rows.Close()
reads := map[string]int64{}
for rows.Next() {
taskID := ""
seq := int64(0)
err = rows.Scan(&taskID, &seq)
if err != nil {
return nil, err
}
reads[taskID] = seq
}
return reads, rows.Err()
}
func (s *Store) MarkSummaryRead(ctx context.Context, login, taskID string, seq int64) error {
return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error {
err := tx.QueryRowContext(ctx, `SELECT id FROM tasks WHERE id = ?`, taskID).Scan(&taskID)
if errors.Is(err, sql.ErrNoRows) {
return fmt.Errorf("task %s: %w", taskID, ErrNotFound)
}
if err != nil {
return err
}
res, err := tx.ExecContext(ctx, `
INSERT INTO summary_reads (login, task_id, seq) VALUES (?, ?, ?)
ON CONFLICT (login, task_id) DO UPDATE SET seq = excluded.seq WHERE excluded.seq > summary_reads.seq
`, login, taskID, seq)
if err != nil {
return err
}
n, err := res.RowsAffected()
if err != nil {
return err
}
if n == 0 {
return nil
}
return emit(api.Event{Kind: "summary.read", Owner: &login, Actor: login, Payload: map[string]any{"task_id": taskID, "seq": seq}})
})
}