basecamp / basecamp/hey-cli

hey reply discards the reply prefill except addressed: drafts save with no subject, wrong sender, and no quoted original

Open
#341 1 comment 1 reaction 0 assignees View on GitHub
Dominant language
Go
Stars
368
Forks
44
Avg merge
15h 15m
Merged PRs (30d)
189

Description

`hey reply` fetches the reply prefill but reads only `addressed`, so every reply draft is saved with no subject, as the wrong sender, and without the quoted original.

`hey reply --draft` saves drafts that show as **"No subject, Me → …"** in HEY's Drafts. The root cause is one discarded response, and it costs three separate things.

## Root cause

`replyRecipientsFromServer` (`internal/cmd/thread_reply.go:83`) calls `GET /entries/{id}/replies/new.json` — but keeps only `Addressed`:

```go
prefilled, err := client.Entries().NewReply(ctx, entryID)
...
addressed := replyRecipients{
To: addressEmails(prefilled.Addressed.Directly),
CC: addressEmails(prefilled.Addressed.Copied),
BCC: addressEmails(prefilled.Addressed.Blindcopied),
}
```

That same response is a `MessageDraft`, which per `spec/hey.smithy:2991` also carries `subject`, `sender` and `content`. All three are dropped.

Verified live against `GET /entries/2239921291/replies/new.json`:

```
subject : 'Re: [SL-1705] Test Bug'
sender : support@studioledger.app (id 215919703)
is_reply: True
content : 2502 chars (quoted original)
```

## 1. The subject cannot be sent at all (spec-level)

`ReplyMessagePayload` has no subject field — `spec/hey.smithy:1863`:

```smithy
structure ReplyMessagePayload {
@required
content: String
}
```

Compare `MessagePayload` for compose (`spec/hey.smithy:1591`), where `subject` is `@required`. So the spec models the server *handing you* a prefilled subject on `NewEntryReply`, then provides no way to send it back. The round trip is broken in the model, and `client.gen.go:1322` inherits it.

**The server does accept it.** Two POSTs to `/entries/2239921291/replies.json`, identical but for one field:

| `message[subject]` | Result | Renders in Drafts as |
|---|---|---|
| omitted (what the SDK sends) | 204 + Location | **`No subject`, Me → …** |
| `"Re: [SL-1705] Test Bug"` | 204 + Location | **`Re: [SL-1705] Test Bug`** |

Note this is only observable in the HTML view of `/entries/drafts`; the JSON index reports `subject: null` for every draft, and `hey draft show` on a reply draft hides `is_reply`/`posting` too — which is likely why it went unnoticed.

## 2. Replies act as the account default sender, not the prefill's

`EntriesService.Reply` (`go/pkg/hey/entries.go:70`) uses `s.client.DefaultSenderID(ctx)`, ignoring `prefilled.Sender`. On an account with extenzions this is wrong: HEY resolves the acting sender to the address the thread was addressed to (here `support@studioledger.app`), while the CLI replies as the account owner. For anyone using HEY for Work as a shared support address, every CLI reply goes out from the wrong identity.

## 3. The quoted original is dropped

`prefilled.Content` holds HEY's quoted thread. `Reply` sends only the caller's content, so CLI replies lose the quote that a reply from the web app or TUI would carry.

## Suggested fix

1. Add `subject: String` to `ReplyMessagePayload` in `spec/hey.smithy` and regenerate.
2. Have `replyRecipientsFromServer` return the whole `MessageDraft`, and let `Reply` accept `subject` and `actingSenderID` overrides defaulting to the prefill's values.
3. Append `prefilled.Content` to the caller's body.

Happy to send a PR if the shape above looks right.

## Environment

- hey-cli 1.2.0 (`58c83f1`), hey-sdk `1312234`
- macOS 26.5.1, HEY for Work

Contributor guide

Open the contributing guide

Research direction

Start with replyRecipientsFromServer in internal/cmd/thread_reply.go and EntriesService.Reply in go/pkg/hey/entries.go, then compare ReplyMessagePayload and MessageDraft in spec/hey.smithy. Check how generated client.gen.go represents reply payloads and how regeneration is performed. Done means reply drafts retain the prefilled subject, sender, and quoted content while preserving existing recipient behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
api, cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
64/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.