From 79be1c40b6f881310063f923ef263e1f21e2574f Mon Sep 17 00:00:00 2001 From: harness-agent Date: Tue, 2 Jun 2026 20:40:19 +0800 Subject: [PATCH] Include mailbox_id in mail +triage output for public mailbox support When mail +triage reads messages from a public/shared mailbox, the structured output now includes the resolved mailbox_id so downstream consumers (e.g. mail +message) can use the correct mailbox instead of defaulting to /user_mailboxes/me. Changes: - Add mailbox_id to every message in JSON/data output - Add mailbox_id as a top-level field in JSON/data output - Add mailbox_id column to table output rows - Update tip text to include --mailbox flag with the resolved mailbox - Add unit tests for message builder field preservation sprint: S1 --- shortcuts/mail/mail_triage.go | 7 +++- shortcuts/mail/mail_triage_test.go | 53 ++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/shortcuts/mail/mail_triage.go b/shortcuts/mail/mail_triage.go index 08507247b..c608e28c4 100644 --- a/shortcuts/mail/mail_triage.go +++ b/shortcuts/mail/mail_triage.go @@ -267,7 +267,11 @@ var MailTriage = common.Shortcut{ switch outFormat { case "json", "data": + for i := range messages { + messages[i]["mailbox_id"] = mailbox + } outData := map[string]interface{}{ + "mailbox_id": mailbox, "messages": messages, "count": len(messages), "has_more": hasMore, @@ -286,6 +290,7 @@ var MailTriage = common.Shortcut{ "from": sanitizeForTerminal(strVal(msg["from"])), "subject": sanitizeForTerminal(strVal(msg["subject"])), "message_id": msg["message_id"], + "mailbox_id": mailbox, } if showLabels { row["labels"] = msg["labels"] @@ -306,7 +311,7 @@ var MailTriage = common.Shortcut{ hint.WriteString(" --page-token " + shellQuote(nextPageToken)) fmt.Fprintln(runtime.IO().ErrOut, hint.String()) } - fmt.Fprintln(runtime.IO().ErrOut, "tip: use mail +message --message-id to read full content") + fmt.Fprintf(runtime.IO().ErrOut, "tip: use mail +message --mailbox %s --message-id to read full content\n", mailbox) } return nil }, diff --git a/shortcuts/mail/mail_triage_test.go b/shortcuts/mail/mail_triage_test.go index 61d04c92d..c6eecb143 100644 --- a/shortcuts/mail/mail_triage_test.go +++ b/shortcuts/mail/mail_triage_test.go @@ -1405,3 +1405,56 @@ func TestParseTriagePageTokenInvalidPrefix(t *testing.T) { } func boolPtr(v bool) *bool { return &v } + + +// --- mailbox_id in output --- + +func TestBuildTriageMessageMetaPreservesFields(t *testing.T) { + msg := map[string]interface{}{ + "message_id": "msg_001", + "subject": "Test subject", + "folder_id": "INBOX", + "thread_id": "thread_001", + "head_from": map[string]interface{}{ + "name": "Alice", + "mail_address": "alice@example.com", + }, + } + got := buildTriageMessageMeta(msg, "msg_001") + if got["message_id"] != "msg_001" { + t.Fatalf("message_id mismatch: %v", got["message_id"]) + } + if got["subject"] != "Test subject" { + t.Fatalf("subject mismatch: %v", got["subject"]) + } + if got["thread_id"] != "thread_001" { + t.Fatalf("thread_id mismatch: %v", got["thread_id"]) + } +} + +func TestBuildTriageMessagesFromSearchItemsIncludesAllFields(t *testing.T) { + raw := []interface{}{ + map[string]interface{}{ + "meta_data": map[string]interface{}{ + "message_biz_id": "biz_msg_100", + "title": "Search hit", + "thread_id": "thread_100", + "create_time": "2026-04-01T12:00:00+08:00", + "from": map[string]interface{}{ + "name": "Bob", + "mail_address": "bob@example.com", + }, + }, + }, + } + got := buildTriageMessagesFromSearchItems(raw) + if len(got) != 1 { + t.Fatalf("expected 1 message, got %d", len(got)) + } + if got[0]["message_id"] != "biz_msg_100" { + t.Fatalf("message_id mismatch: %v", got[0]["message_id"]) + } + if got[0]["subject"] != "Search hit" { + t.Fatalf("subject mismatch: %v", got[0]["subject"]) + } +}