2026-10-15 19:44:53 -07:00
|
|
|
package agents
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"fmt"
|
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
|
2026-10-18 15:32:07 -07:00
|
|
|
"g.fc.run/ai/byre/internal/api"
|
|
|
|
|
"g.fc.run/ai/byre/internal/store"
|
2026-10-15 19:44:53 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func (m *Manager) mergeNote(ctx context.Context, task api.Task, login string) (string, error) {
|
|
|
|
|
handoffs, err := m.store.TaskHandoffs(ctx, task.Id)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
reviews, err := m.store.ListReviews(ctx, task.Id)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
answered, err := m.store.ListInbox(ctx, store.InboxFilter{TaskID: task.Id, State: api.Answered})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
2026-10-16 10:08:08 -07:00
|
|
|
summary, err := m.store.TaskSummary(ctx, task.Id)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
2026-10-15 19:44:53 -07:00
|
|
|
|
|
|
|
|
b := &strings.Builder{}
|
|
|
|
|
fmt.Fprintf(b, "# %s\n\n", task.MergeTitle)
|
|
|
|
|
fmt.Fprintf(b, "byre task %s, %q, created by %s, merged by %s.\n", task.Id, task.Title, task.CreatedBy, login)
|
|
|
|
|
if task.TodoItem != nil {
|
|
|
|
|
fmt.Fprintf(b, "Started from the TODO item %q.\n", *task.TodoItem)
|
|
|
|
|
}
|
|
|
|
|
if task.ForkedFrom != nil && task.ForkedAt != nil {
|
|
|
|
|
fmt.Fprintf(b, "Forked from task %s at snapshot %d.\n", *task.ForkedFrom, *task.ForkedAt)
|
|
|
|
|
}
|
|
|
|
|
fmt.Fprintf(b, "Full transcripts: the events of task %s in byre (GET /api/events?task_id=%s).\n", task.Id, task.Id)
|
|
|
|
|
|
2026-10-16 10:08:08 -07:00
|
|
|
if strings.TrimSpace(summary) != "" {
|
|
|
|
|
fmt.Fprintf(b, "\n## Summary\n\n%s\n", strings.TrimSpace(summary))
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-15 19:44:53 -07:00
|
|
|
if len(handoffs) > 0 {
|
|
|
|
|
b.WriteString("\n## Handoffs\n")
|
|
|
|
|
for _, h := range handoffs {
|
|
|
|
|
fmt.Fprintf(b, "\n### Session %s, %s\n\n%s\n", h.SessionID, h.At.Format(time.RFC3339), strings.TrimSpace(h.Text))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(reviews) > 0 {
|
|
|
|
|
b.WriteString("\n## Reviews\n")
|
|
|
|
|
for _, r := range reviews {
|
|
|
|
|
fmt.Fprintf(b, "\n### Snapshot %d, %s %s: %s\n", r.SnapshotN, r.Vendor, r.Model, r.State)
|
|
|
|
|
if r.Error != "" {
|
|
|
|
|
fmt.Fprintf(b, "\n%s\n", r.Error)
|
|
|
|
|
}
|
|
|
|
|
if r.Result == nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
for _, key := range []string{"change", "summary"} {
|
|
|
|
|
text, _ := (*r.Result)[key].(string)
|
|
|
|
|
if strings.TrimSpace(text) != "" {
|
|
|
|
|
fmt.Fprintf(b, "\n%s\n", strings.TrimSpace(text))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-18 15:06:06 -07:00
|
|
|
if len(answered) > 0 {
|
2026-10-15 19:44:53 -07:00
|
|
|
b.WriteString("\n## Decisions\n")
|
2026-10-18 15:06:06 -07:00
|
|
|
for _, item := range answered {
|
2026-10-15 19:44:53 -07:00
|
|
|
fmt.Fprintf(b, "\n### %s\n", item.Payload["question"])
|
|
|
|
|
background, _ := item.Payload["context"].(string)
|
|
|
|
|
if strings.TrimSpace(background) != "" {
|
|
|
|
|
fmt.Fprintf(b, "\n%s\n", strings.TrimSpace(background))
|
|
|
|
|
}
|
|
|
|
|
b.WriteString("\n")
|
|
|
|
|
for _, r := range item.Responses {
|
|
|
|
|
b.WriteString(decisionLine(item, r))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return b.String(), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decisionLine(item api.InboxItem, r api.InboxResponse) string {
|
|
|
|
|
text := ""
|
|
|
|
|
if r.Text != nil {
|
|
|
|
|
text = strings.TrimSpace(*r.Text)
|
|
|
|
|
}
|
|
|
|
|
switch r.Type {
|
|
|
|
|
case api.Option:
|
|
|
|
|
line := fmt.Sprintf("%s chose: %s\n", r.User, strings.Join(*r.Options, "; "))
|
|
|
|
|
if item.Payload["multiple"] == true {
|
|
|
|
|
line = fmt.Sprintf("%s checked: %s\n", r.User, strings.Join(*r.Options, "; "))
|
|
|
|
|
}
|
|
|
|
|
if text != "" {
|
|
|
|
|
line += fmt.Sprintf("%s added: %s\n", r.User, text)
|
|
|
|
|
}
|
|
|
|
|
return line
|
|
|
|
|
case api.Other:
|
|
|
|
|
return fmt.Sprintf("%s answered: %s\n", r.User, text)
|
|
|
|
|
}
|
|
|
|
|
return ""
|
|
|
|
|
}
|