import * as z from "zod" import { defineAction } from "../../../automation/actions" import { EMAIL_ORIGIN_TOKEN } from "../../../lib/email-origin" import { getGmailApi, sendReply, } from "@automate.ax/integration-contracts/gmail" import { GMAIL_SEND_AND_METADATA_REQUIREMENT } from "../lib/scopes" import { MESSAGE_METADATA_SCHEMA, REPLY_OPTIONS_SCHEMA, } from "@automate.ax/integration-contracts/gmail" /** * Replies to the latest received message in a Gmail thread. * * Sent messages are ignored, so archived conversations remain replyable. */ export const replyToGmailThread = defineAction("Reply to Gmail thread") .describe("Replies to the latest received message in a Gmail thread.") .account("google", GMAIL_SEND_AND_METADATA_REQUIREMENT) .input( REPLY_OPTIONS_SCHEMA.extend({ /** Immutable Gmail thread ID receiving the reply. */ threadId: z.string().min(1), }), ) .output(MESSAGE_METADATA_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(async ({ account, input, runtime }) => { const gmailApi = getGmailApi(account.secret) const latestReceivedMessage = [ ...(( await gmailApi.users.threads.get({ format: "metadata", id: input.threadId, userId: "me", }) ).data.messages ?? []), ] .filter((message) => !message.labelIds?.includes("SENT")) .toSorted( (a, b) => Number(b.internalDate ?? "0") - Number(a.internalDate ?? "0"), ) .at(0) if (!latestReceivedMessage) { throw new Error("Gmail thread has no received messages to reply to.") } return await sendReply( gmailApi, latestReceivedMessage, input, runtime[EMAIL_ORIGIN_TOKEN], ) })