Mark the lead's messages and answers as the lead's, not the human's
This commit is contained in:
@@ -531,6 +531,7 @@ func deliveryMessage(pending []store.Pending) string {
|
||||
b := &strings.Builder{}
|
||||
for i, p := range pending {
|
||||
r := p.Response
|
||||
who := actorName(r.User)
|
||||
if i > 0 {
|
||||
b.WriteString("\n")
|
||||
}
|
||||
@@ -540,27 +541,27 @@ func deliveryMessage(pending []store.Pending) string {
|
||||
switch r.Type {
|
||||
case api.Option:
|
||||
if p.Item.Payload["multiple"] == true {
|
||||
fmt.Fprintf(b, "%s checked:\n", r.User)
|
||||
fmt.Fprintf(b, "%s checked:\n", who)
|
||||
for _, o := range *r.Options {
|
||||
fmt.Fprintf(b, "- %s\n", o)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(b, "%s chose: %s\n", r.User, (*r.Options)[0])
|
||||
fmt.Fprintf(b, "%s chose: %s\n", who, (*r.Options)[0])
|
||||
}
|
||||
if r.Text != nil && strings.TrimSpace(*r.Text) != "" {
|
||||
fmt.Fprintf(b, "%s added: %s\n", r.User, *r.Text)
|
||||
fmt.Fprintf(b, "%s added: %s\n", who, *r.Text)
|
||||
}
|
||||
case api.Other:
|
||||
text := ""
|
||||
if r.Text != nil {
|
||||
text = *r.Text
|
||||
}
|
||||
fmt.Fprintf(b, "%s answered (none of your options): %s\n", r.User, text)
|
||||
fmt.Fprintf(b, "%s answered (none of your options): %s\n", who, text)
|
||||
fmt.Fprintf(b, "If this asks you something back, answer by calling ask_human with thread_id %q.\n", p.Item.ThreadId)
|
||||
}
|
||||
|
||||
if len(r.Images) > 0 {
|
||||
fmt.Fprintf(b, "%s attached %d image(s) to this response; they come with this message.\n", r.User, len(r.Images))
|
||||
fmt.Fprintf(b, "%s attached %d image(s) to this response; they come with this message.\n", who, len(r.Images))
|
||||
}
|
||||
|
||||
for _, a := range r.Attachments {
|
||||
|
||||
+19
-1
@@ -49,6 +49,24 @@ func isLeadActor(actor string) bool {
|
||||
return strings.HasSuffix(actor, " (lead)")
|
||||
}
|
||||
|
||||
func leadOwner(actor string) string {
|
||||
return strings.TrimSuffix(actor, " (lead)")
|
||||
}
|
||||
|
||||
func actorName(actor string) string {
|
||||
if !isLeadActor(actor) {
|
||||
return actor
|
||||
}
|
||||
return leadOwner(actor) + "'s lead agent"
|
||||
}
|
||||
|
||||
func agentText(actor, text string) string {
|
||||
if !isLeadActor(actor) {
|
||||
return text
|
||||
}
|
||||
return fmt.Sprintf("This message is from %s, not from %s:\n\n%s", actorName(actor), leadOwner(actor), text)
|
||||
}
|
||||
|
||||
func humanActor(actor string) bool {
|
||||
return actor != "byre" && actor != agentActor && actor != boardActor && !strings.HasSuffix(actor, leadActor(""))
|
||||
}
|
||||
@@ -645,7 +663,7 @@ func (m *Manager) answeredText(ctx context.Context, item api.InboxItem) string {
|
||||
answer = strings.TrimSpace(answer + " " + *r.Text)
|
||||
}
|
||||
recommended := strings.Join(anyStrings(item.Payload["recommended"]), "; ")
|
||||
return fmt.Sprintf("%s: %s answered question %s %q: %s\nThe agent recommended: %s", m.taskLabel(ctx, item.TaskId), r.User, item.Id, clip(fmt.Sprint(item.Payload["question"]), 300), clip(answer, 600), clip(recommended, 600))
|
||||
return fmt.Sprintf("%s: %s answered question %s %q: %s\nThe agent recommended: %s", m.taskLabel(ctx, item.TaskId), actorName(r.User), item.Id, clip(fmt.Sprint(item.Payload["question"]), 300), clip(answer, 600), clip(recommended, 600))
|
||||
}
|
||||
|
||||
func remarshal(from any, to any) error {
|
||||
|
||||
@@ -139,7 +139,7 @@ func (m *Manager) leadTools(l *live) []mcp.Tool {
|
||||
m.mu.Lock()
|
||||
m.leadAnswered[c.ItemId] = true
|
||||
m.mu.Unlock()
|
||||
_, err = m.Respond(ctx, user.Login, []api.InboxResponseCreate{c})
|
||||
_, err = m.Respond(ctx, leadActor(user.Login), []api.InboxResponseCreate{c})
|
||||
if err != nil {
|
||||
m.mu.Lock()
|
||||
delete(m.leadAnswered, c.ItemId)
|
||||
@@ -1056,7 +1056,7 @@ func transcriptLine(ev api.Event, root string) string {
|
||||
case boardActor:
|
||||
return ""
|
||||
}
|
||||
return ev.Actor + ": " + text("text")
|
||||
return actorName(ev.Actor) + ": " + text("text")
|
||||
case "board.posted":
|
||||
return fmt.Sprintf("board post by %s: %s", postAuthor(ev), text("text"))
|
||||
case "agent.message":
|
||||
|
||||
@@ -603,7 +603,7 @@ func (m *Manager) deliver(ctx context.Context, sess api.AgentSession, task api.T
|
||||
}
|
||||
|
||||
m.beginTurn(l, compacting)
|
||||
err = m.send(ctx, l, text, imgs)
|
||||
err = m.send(ctx, l, agentText(actor, text), imgs)
|
||||
if err != nil {
|
||||
m.endMergeTurn(sess.Id, false)
|
||||
return err
|
||||
@@ -684,7 +684,7 @@ func (m *Manager) message(ctx context.Context, sess api.AgentSession, task api.T
|
||||
return err
|
||||
}
|
||||
m.beginTurn(l, compacting)
|
||||
return m.send(ctx, l, text, imgs)
|
||||
return m.send(ctx, l, agentText(actor, text), imgs)
|
||||
}
|
||||
|
||||
func (m *Manager) send(ctx context.Context, l *live, text string, imgs []image) error {
|
||||
|
||||
@@ -92,18 +92,19 @@ func decisionLine(item api.InboxItem, r api.InboxResponse) string {
|
||||
if r.Text != nil {
|
||||
text = strings.TrimSpace(*r.Text)
|
||||
}
|
||||
who := actorName(r.User)
|
||||
switch r.Type {
|
||||
case api.Option:
|
||||
line := fmt.Sprintf("%s chose: %s\n", r.User, strings.Join(*r.Options, "; "))
|
||||
line := fmt.Sprintf("%s chose: %s\n", who, strings.Join(*r.Options, "; "))
|
||||
if item.Payload["multiple"] == true {
|
||||
line = fmt.Sprintf("%s checked: %s\n", r.User, strings.Join(*r.Options, "; "))
|
||||
line = fmt.Sprintf("%s checked: %s\n", who, strings.Join(*r.Options, "; "))
|
||||
}
|
||||
if text != "" {
|
||||
line += fmt.Sprintf("%s added: %s\n", r.User, text)
|
||||
line += fmt.Sprintf("%s added: %s\n", who, text)
|
||||
}
|
||||
return line
|
||||
case api.Other:
|
||||
return fmt.Sprintf("%s answered: %s\n", r.User, text)
|
||||
return fmt.Sprintf("%s answered: %s\n", who, text)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -267,6 +267,10 @@ func (m *Manager) recordQueued(ctx context.Context, l *live, msgs []queued) stri
|
||||
fmt.Fprintf(b, "While you were working, %s\n\nTake it into account now.", q.text)
|
||||
continue
|
||||
}
|
||||
if isLeadActor(q.actor) {
|
||||
fmt.Fprintf(b, "%s (not %s) sent you this message while you were working; take it into account now:\n\n%s", actorName(q.actor), leadOwner(q.actor), q.text)
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(b, "%s sent you this message while you were working; take it into account now:\n\n%s", q.actor, q.text)
|
||||
}
|
||||
slog.Info("queued messages sent mid-turn", "session", l.id, "count", len(msgs))
|
||||
|
||||
@@ -172,7 +172,7 @@ func (m *Manager) post(ctx context.Context, task api.Task, from poster, text str
|
||||
return err
|
||||
}
|
||||
|
||||
who := from.actor
|
||||
who := actorName(from.actor)
|
||||
if from.member != "" {
|
||||
who = fmt.Sprintf("%q", from.member)
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ func insertResponse(ctx context.Context, tx *sql.Tx, resp api.InboxResponse) err
|
||||
}
|
||||
|
||||
_, err = tx.ExecContext(ctx, `
|
||||
INSERT INTO inbox_responses (id, item_id, user_login, type, options, text, images, attachments, created_at)
|
||||
INSERT INTO inbox_responses (id, item_id, actor, type, options, text, images, attachments, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`, resp.Id, resp.ItemId, resp.User, string(resp.Type), options, resp.Text, string(images), string(attachments), formatTime(resp.CreatedAt))
|
||||
return err
|
||||
@@ -392,7 +392,7 @@ func getItem(ctx context.Context, q querier, id string) (api.InboxItem, error) {
|
||||
|
||||
func getResponses(ctx context.Context, q querier, itemID string) ([]api.InboxResponse, error) {
|
||||
rows, err := q.QueryContext(ctx, `
|
||||
SELECT id, item_id, user_login, type, options, text, images, attachments, created_at, delivered_at, snapshot_n
|
||||
SELECT id, item_id, actor, type, options, text, images, attachments, created_at, delivered_at, snapshot_n
|
||||
FROM inbox_responses WHERE item_id = ? ORDER BY created_at
|
||||
`, itemID)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
CREATE TABLE inbox_items_next (
|
||||
id TEXT PRIMARY KEY,
|
||||
project_id TEXT NOT NULL REFERENCES projects(id),
|
||||
task_id TEXT NOT NULL REFERENCES tasks(id),
|
||||
agent_session_id TEXT NOT NULL REFERENCES agent_sessions(id),
|
||||
thread_id TEXT NOT NULL,
|
||||
priority INTEGER NOT NULL DEFAULT 0,
|
||||
blocking INTEGER NOT NULL DEFAULT 1,
|
||||
payload TEXT NOT NULL,
|
||||
state TEXT NOT NULL,
|
||||
snoozed_until TEXT,
|
||||
created_at TEXT NOT NULL,
|
||||
resolved_by TEXT,
|
||||
resolved_at TEXT
|
||||
);
|
||||
INSERT INTO inbox_items_next SELECT id, project_id, task_id, agent_session_id, thread_id, priority, blocking, payload, state, snoozed_until, created_at, resolved_by, resolved_at FROM inbox_items;
|
||||
DROP TABLE inbox_items;
|
||||
ALTER TABLE inbox_items_next RENAME TO inbox_items;
|
||||
CREATE INDEX inbox_items_open ON inbox_items(state, created_at);
|
||||
CREATE INDEX inbox_items_session ON inbox_items(agent_session_id, state);
|
||||
|
||||
CREATE TABLE inbox_responses_next (
|
||||
id TEXT PRIMARY KEY,
|
||||
item_id TEXT NOT NULL REFERENCES inbox_items(id),
|
||||
actor TEXT NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
text TEXT,
|
||||
attachments TEXT NOT NULL,
|
||||
snooze_until TEXT,
|
||||
created_at TEXT NOT NULL,
|
||||
delivered_at TEXT,
|
||||
options TEXT,
|
||||
images TEXT NOT NULL DEFAULT '[]',
|
||||
snapshot_n INTEGER
|
||||
);
|
||||
INSERT INTO inbox_responses_next SELECT id, item_id, user_login, type, text, attachments, snooze_until, created_at, delivered_at, options, images, snapshot_n FROM inbox_responses;
|
||||
DROP TABLE inbox_responses;
|
||||
ALTER TABLE inbox_responses_next RENAME TO inbox_responses;
|
||||
CREATE INDEX inbox_responses_item ON inbox_responses(item_id, created_at);
|
||||
Reference in New Issue
Block a user