Spaces:
Sleeping
Sleeping
| const ADDON_CONFIG = { | |
| TRIAGE_API_URL: 'https://REPLACE_WITH_CLOUD_RUN_URL/api/triage', | |
| TRIAGE_API_KEY: 'REPLACE_WITH_TRIAGE_API_KEY' | |
| }; | |
| function buildAddonHome(e) { | |
| const section = CardService.newCardSection() | |
| .addWidget(CardService.newTextParagraph().setText( | |
| '<b>Mail Triage Assistant</b><br/>Open any Gmail message to see AI triage, suggested actions, and a reply draft.' | |
| )); | |
| const card = CardService.newCardBuilder() | |
| .setHeader(CardService.newCardHeader().setTitle('Mail Triage Assistant')) | |
| .addSection(section) | |
| .build(); | |
| return card; | |
| } | |
| function buildContextCard(e) { | |
| try { | |
| const message = getOpenMessage_(e); | |
| const triage = callTriageApi_({ | |
| subject: message.getSubject() || '', | |
| sender: message.getFrom() || '', | |
| body: message.getPlainBody() || '' | |
| }); | |
| const actions = (triage.suggested_actions || []).join(', ') || 'None'; | |
| const section = CardService.newCardSection() | |
| .addWidget(CardService.newKeyValue().setTopLabel('Category').setContent(String(triage.category || 'unknown'))) | |
| .addWidget(CardService.newKeyValue().setTopLabel('Urgency').setContent(String(triage.urgency || 'unknown'))) | |
| .addWidget(CardService.newKeyValue().setTopLabel('Suggested Actions').setContent(actions)) | |
| .addWidget(CardService.newTextParagraph().setText('<b>Reasoning:</b><br/>' + sanitize_(triage.reasoning || 'N/A'))) | |
| .addWidget( | |
| CardService.newTextInput() | |
| .setFieldName('draftReply') | |
| .setTitle('Reply Draft') | |
| .setMultiline(true) | |
| .setValue(String(triage.suggested_reply || '')) | |
| ); | |
| const draftAction = CardService.newAction() | |
| .setFunctionName('createDraftReplyFromCard') | |
| .setParameters({ messageId: String(e.gmail.messageId || '') }); | |
| section.addWidget( | |
| CardService.newTextButton() | |
| .setText('Create Gmail Draft Reply') | |
| .setOnClickAction(draftAction) | |
| ); | |
| const card = CardService.newCardBuilder() | |
| .setHeader(CardService.newCardHeader().setTitle('AI Triage Results')) | |
| .addSection(section) | |
| .build(); | |
| return [card]; | |
| } catch (err) { | |
| const errorCard = CardService.newCardBuilder() | |
| .setHeader(CardService.newCardHeader().setTitle('Mail Triage Assistant')) | |
| .addSection( | |
| CardService.newCardSection() | |
| .addWidget(CardService.newTextParagraph().setText('Could not process this email.<br/>' + sanitize_(String(err)))) | |
| ) | |
| .build(); | |
| return [errorCard]; | |
| } | |
| } | |
| function createDraftReplyFromCard(e) { | |
| const message = getOpenMessage_(e); | |
| const replyText = getFormText_(e, 'draftReply'); | |
| if (!replyText || !replyText.trim()) { | |
| return CardService.newActionResponseBuilder() | |
| .setNotification(CardService.newNotification().setText('Reply draft is empty.')) | |
| .build(); | |
| } | |
| message.createDraftReply(replyText); | |
| return CardService.newActionResponseBuilder() | |
| .setNotification(CardService.newNotification().setText('Draft reply created in Gmail.')) | |
| .build(); | |
| } | |
| function getOpenMessage_(e) { | |
| const accessToken = e && e.gmail && e.gmail.accessToken; | |
| const messageId = e && e.gmail && e.gmail.messageId; | |
| if (!accessToken || !messageId) { | |
| throw new Error('Missing Gmail event context (access token or message id).'); | |
| } | |
| GmailApp.setCurrentMessageAccessToken(accessToken); | |
| return GmailApp.getMessageById(messageId); | |
| } | |
| function getFormText_(e, fieldName) { | |
| try { | |
| return e.commonEventObject.formInputs[fieldName].stringInputs.value[0] || ''; | |
| } catch (err) { | |
| return ''; | |
| } | |
| } | |
| function sanitize_(s) { | |
| return String(s) | |
| .replace(/&/g, '&') | |
| .replace(/</g, '<') | |
| .replace(/>/g, '>'); | |
| } | |
| function callTriageApi_(payload) { | |
| const response = UrlFetchApp.fetch(ADDON_CONFIG.TRIAGE_API_URL, { | |
| method: 'post', | |
| contentType: 'application/json', | |
| headers: { | |
| 'x-api-key': ADDON_CONFIG.TRIAGE_API_KEY | |
| }, | |
| payload: JSON.stringify(payload), | |
| muteHttpExceptions: true | |
| }); | |
| const code = response.getResponseCode(); | |
| if (code < 200 || code >= 300) { | |
| throw new Error('Triage API HTTP ' + code + ': ' + response.getContentText()); | |
| } | |
| return JSON.parse(response.getContentText()); | |
| } | |