Skip to content

Add sent mail listing - #473

Open
robzolkos wants to merge 7 commits into
mainfrom
rob/issue-469-sent-mail
Open

robzolkos wants to merge 7 commits into
mainfrom
rob/issue-469-sent-mail

Conversation

@robzolkos

@robzolkos robzolkos commented Sep 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • add first-class hey sent with one latest outbound message per thread, newest first
  • match HEY's compact human recipient summary while returning exact to, cc, and bcc arrays in JSON
  • include thread ID, subject, summary, delivery time, and app URL for reconciliation scripts
  • support --limit, --all, --page, --ids-only, --count, Markdown, and the standard JSON formats
  • document the command and cover its output, pagination, limits, help surface, and smoke contract

Closes #469.

Dependencies

  • haystack#8874 adds recipients, delivery time, and Sent pagination headers
  • hey-sdk#222 models those fields and exposes paginated Sent reads

This branch pins the SDK PR commit with a Go pseudo-version so CI and review are reproducible. It must be changed to the published SDK release before this PR merges.

Tests

  • make test
  • make lint
  • make build
  • go test -c for tests/smoke
  • built ./bin/hey against a real HEY account through a redacting validator: three rows checked; thread ID, subject, sent time, app URL, and array shapes valid; no message content or personal data printed or retained

Production does not expose recipient data until the Haystack dependency deploys, so that real-account check correctly found no populated recipient arrays. Unit and smoke contracts cover the new response shape.


Summary by cubic

Adds hey sent, a first-class command that lists the latest outbound message in each thread, newest first. It provides thread and delivery metadata for scripts while matching HEY's compact human-readable recipient summary. Closes #469.

New Features

  • JSON includes exact to, cc, and bcc arrays, thread ID, subject, summary, delivery time, and app URL; older servers report sent_at as null.
  • Supports --limit (reading pages until the requested count is reached), --all, --page, --ids-only, --count, Markdown, and the standard JSON formats.
  • --all follows pagination for up to 100 pages; notices suggest --all when more pages remain and a sanitized --page cursor when the run was truncated.
  • Documentation, API coverage, help output, unit tests, and smoke coverage include the new command and its edge cases.

Dependencies

  • Pins github.com/basecamp/hey-sdk/go to a commit pseudo-version; replace it with the published SDK release before merging.
  • Recipient arrays remain empty until HEY's backend exposes Sent recipient data.

Written for commit 75fe8f3. Summary will update on new commits.

Review in cubic

Copilot AI balanced review requested due to automatic review settings September 20, 2026 18:14
@robzolkos
robzolkos requested a review from a team as a code owner September 20, 2026 18:14

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. Cursor Security Agent completed successfully with no findings that need human review; Cursor Bugbot was not running on this PR, so that signal was skipped. No reviewers were assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Cursor handling, delivery-time accuracy, terminal sanitization, and the temporary SDK pin remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 4 Medium severity

Open (4)
What changed in this PR

Adds hey sent to list the latest outbound message per thread for reconciliation and scripting.

Changes:

  • Adds paginated Sent output with recipient, timestamp, and thread metadata.
  • Adds command documentation, help entries, and tests.
  • Pins and synchronizes the supporting SDK model changes.

[!TIP]
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.

File Description
tests/​smoke/​sent_test.go Adds the Sent smoke contract.
internal/​mcpserver/​model/​PROVENANCE.json Updates model provenance.
internal/​mcpserver/​model/​openapi.json Adds Sent entry fields.
internal/​cmd/​sent.go Implements the new command.
internal/​cmd/​sent_test.go Tests output and pagination.
internal/​cmd/​root.go Registers hey sent.
internal/​cmd/​help.go Adds Sent to curated help.
internal/​cmd/​help_test.go Updates the help snapshot.
go.sum Updates SDK checksums.
go.mod Pins the supporting SDK revision.
docs/​cli.md Documents Sent usage and output.
.surface Records the new command surface.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread go.mod
Comment thread internal/cmd/sent.go Outdated
Comment thread internal/cmd/sent.go Outdated
Comment thread internal/cmd/sent.go Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Approval depends on coordinated backend deployment, an SDK release, and resolution of the remaining output-contract issues.

Review effort: Balanced
Findings: 2 Medium severity

Open (2)
Resolved since last review (4)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Show continuation notice when styled output is empty

internal/​cmd/​sent.go:181

When the first page is empty but still includes a continuation cursor, notice tells the user that more results are available. This early return suppresses that notice only for styled output, leaving the user with “No sent messages.” and no way to discover the continuation. Print the notice before returning, as the non-empty styled path does.

Comment thread internal/cmd/sent.go
Comment thread tests/smoke/sent_test.go Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Limited-result notices can report an incorrect total, and empty summaries can make documented output fields disappear.

Review effort: Balanced
Findings: None

Resolved since last review (3)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Preserve empty summary fields in Sent output

internal/​cmd/​sent.go:49

Both Sent projections mark summary as omitempty. Attachment-only sends can validly have an empty summary, so JSON then omits the documented key, and Markdown omits the entire summary column when every row is empty. Remove omitempty from both tags to keep the output shape stable with an empty string/cell.

Medium severity Avoid reporting partial page count as total results

internal/​cmd/​sent.go:104

When --limit trims a fetched page, len(collected.Items) is only the number fetched so far. If collected.Cursor is still non-empty, the current notice incorrectly presents that value as the server total (the new test's page 2 advertises page 3 but reports “Showing 2 of 3 results”). Use the existing non-total pagination notice while another cursor exists, and update the test expectation.

@robzolkos

Copy link
Copy Markdown
Collaborator Author

Fixed the latest review concerns in bc05bbf. Empty summaries now remain in JSON and Markdown, and a trimmed page with a continuation cursor no longer reports the fetched partial page as the total result count.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The API inventory still needs its Sent mapping, and the temporary SDK revision must be replaced before merge.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 Low severity

Open (1)
Resolved since last review (1)

Comment thread internal/cmd/sent.go

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

It has unresolved pagination and timezone-test issues and depends on unpublished cross-repository API changes.

Review effort: Balanced
Findings: None

Resolved since last review (2)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Handle empty pages with cursors when using --all

internal/​cmd/​sent.go:99

With --all, collectPages stops when it reads an empty page even if that page still carries a cursor. In that case this notice says “Use --all” although --all was already used, while next_page contains the cursor needed to resume. Emit a continuation notice for this case and add coverage for the existing empty-page test with --all.

Medium severity Test hard-codes UTC date instead of using local timezone

internal/​cmd/​sent_test.go:110

This expected date depends on the machine's local timezone because formatSentTimestamp converts active_at with Local(). In UTC+10, for example, this timestamp renders as 2026-09-20, so the test fails even though the output is correct. Derive the expected date in time.Local instead of hard-coding the UTC date.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a Sent / outbound listing (search and box cannot list mail you sent)

2 participants