-// whatsappSend sends text to chat, the ID of a private chat or a group, and
-// returns the answer of the tool. id names the send: a call with an id that has
-// a record gives the answer of the record and sends nothing, and the same id
-// with another chat or text is an error. The record "sending" is durable before
-// the send, so a stop of the daemon during the send gives an answer that the
-// result is unknown, and not a second send. A disconnected WhatsApp sends
-// nothing and makes no record. link gives the device, the client, and the own
-// IDs, groups the names of the groups, and state the send records. The clock
-// gives the times of the records and the time zone of the answer.
-func whatsappSend(ctx context.Context, link WhatsAppLink, groups *WhatsAppGroups, state *WhatsAppState, clock func() time.Time, id, chat, text string) (string, error) {
+// whatsappSend sends text and an optional stored image to chat, the ID of a
+// private chat or a group, and returns the answer of the tool. id names the
+// send: a call with an id that has a record gives the answer of the record and
+// sends nothing, and the same id with another chat, text, or image is an error.
+// The record "sending" is durable before the send, so a stop of the daemon
+// during the send gives an answer that the result is unknown, and not a second
+// send. A disconnected WhatsApp sends nothing and makes no record. link gives
+// the device, the client, and the own IDs, groups the names of the groups, and
+// state the send records. The clock gives the times of the records and the time
+// zone of the answer. Image names are checked before the record is written, and
+// uploads start only after the record is durable. Text-only records keep their
+// text digest.
+func whatsappSend(ctx context.Context, link WhatsAppLink, groups *WhatsAppGroups, state *WhatsAppState, images *ImageStore, clock func() time.Time, id, chat, text, image string) (string, error) {