@divyacon/piece-gmail 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/LICENSE.MIT-AP +24 -0
  2. package/README.md +8 -2
  3. package/dist/index.d.ts +6 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +111 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/lib/actions/ai-get-message-action.d.ts +7 -0
  8. package/dist/lib/actions/ai-get-message-action.d.ts.map +1 -0
  9. package/dist/lib/actions/ai-get-message-action.js +24 -0
  10. package/dist/lib/actions/ai-get-message-action.js.map +1 -0
  11. package/dist/lib/actions/ai-reply-to-thread-action.d.ts +16 -0
  12. package/dist/lib/actions/ai-reply-to-thread-action.d.ts.map +1 -0
  13. package/dist/lib/actions/ai-reply-to-thread-action.js +24 -0
  14. package/dist/lib/actions/ai-reply-to-thread-action.js.map +1 -0
  15. package/dist/lib/actions/ai-search-email-action.d.ts +21 -0
  16. package/dist/lib/actions/ai-search-email-action.d.ts.map +1 -0
  17. package/dist/lib/actions/ai-search-email-action.js +24 -0
  18. package/dist/lib/actions/ai-search-email-action.js.map +1 -0
  19. package/dist/lib/actions/ai-send-email-action.d.ts +18 -0
  20. package/dist/lib/actions/ai-send-email-action.d.ts.map +1 -0
  21. package/dist/lib/actions/ai-send-email-action.js +24 -0
  22. package/dist/lib/actions/ai-send-email-action.js.map +1 -0
  23. package/dist/lib/actions/create-draft-action.d.ts +16 -0
  24. package/dist/lib/actions/create-draft-action.d.ts.map +1 -0
  25. package/dist/lib/actions/create-draft-action.js +137 -0
  26. package/dist/lib/actions/create-draft-action.js.map +1 -0
  27. package/dist/lib/actions/create-draft-reply-action.d.ts +17 -0
  28. package/dist/lib/actions/create-draft-reply-action.d.ts.map +1 -0
  29. package/dist/lib/actions/create-draft-reply-action.js +269 -0
  30. package/dist/lib/actions/create-draft-reply-action.js.map +1 -0
  31. package/dist/lib/actions/delete-draft-action.d.ts +7 -0
  32. package/dist/lib/actions/delete-draft-action.d.ts.map +1 -0
  33. package/dist/lib/actions/delete-draft-action.js +62 -0
  34. package/dist/lib/actions/delete-draft-action.js.map +1 -0
  35. package/dist/lib/actions/forward-message-action.d.ts +12 -0
  36. package/dist/lib/actions/forward-message-action.d.ts.map +1 -0
  37. package/dist/lib/actions/forward-message-action.js +139 -0
  38. package/dist/lib/actions/forward-message-action.js.map +1 -0
  39. package/dist/lib/actions/get-attachment-action.d.ts +9 -0
  40. package/dist/lib/actions/get-attachment-action.d.ts.map +1 -0
  41. package/dist/lib/actions/get-attachment-action.js +80 -0
  42. package/dist/lib/actions/get-attachment-action.js.map +1 -0
  43. package/dist/lib/actions/get-draft-action.d.ts +7 -0
  44. package/dist/lib/actions/get-draft-action.d.ts.map +1 -0
  45. package/dist/lib/actions/get-draft-action.js +56 -0
  46. package/dist/lib/actions/get-draft-action.js.map +1 -0
  47. package/dist/lib/actions/get-label-action.d.ts +7 -0
  48. package/dist/lib/actions/get-label-action.d.ts.map +1 -0
  49. package/dist/lib/actions/get-label-action.js +55 -0
  50. package/dist/lib/actions/get-label-action.js.map +1 -0
  51. package/dist/lib/actions/get-mail-action.d.ts +7 -0
  52. package/dist/lib/actions/get-mail-action.d.ts.map +1 -0
  53. package/dist/lib/actions/get-mail-action.js +44 -0
  54. package/dist/lib/actions/get-mail-action.js.map +1 -0
  55. package/dist/lib/actions/get-profile-action.d.ts +5 -0
  56. package/dist/lib/actions/get-profile-action.d.ts.map +1 -0
  57. package/dist/lib/actions/get-profile-action.js +43 -0
  58. package/dist/lib/actions/get-profile-action.js.map +1 -0
  59. package/dist/lib/actions/get-thread-action.d.ts +9 -0
  60. package/dist/lib/actions/get-thread-action.d.ts.map +1 -0
  61. package/dist/lib/actions/get-thread-action.js +53 -0
  62. package/dist/lib/actions/get-thread-action.js.map +1 -0
  63. package/dist/lib/actions/list-drafts-action.d.ts +8 -0
  64. package/dist/lib/actions/list-drafts-action.d.ts.map +1 -0
  65. package/dist/lib/actions/list-drafts-action.js +62 -0
  66. package/dist/lib/actions/list-drafts-action.js.map +1 -0
  67. package/dist/lib/actions/list-history-action.d.ts +9 -0
  68. package/dist/lib/actions/list-history-action.d.ts.map +1 -0
  69. package/dist/lib/actions/list-history-action.js +74 -0
  70. package/dist/lib/actions/list-history-action.js.map +1 -0
  71. package/dist/lib/actions/list-labels-action.d.ts +5 -0
  72. package/dist/lib/actions/list-labels-action.d.ts.map +1 -0
  73. package/dist/lib/actions/list-labels-action.js +47 -0
  74. package/dist/lib/actions/list-labels-action.js.map +1 -0
  75. package/dist/lib/actions/list-threads-action.d.ts +10 -0
  76. package/dist/lib/actions/list-threads-action.d.ts.map +1 -0
  77. package/dist/lib/actions/list-threads-action.js +74 -0
  78. package/dist/lib/actions/list-threads-action.js.map +1 -0
  79. package/dist/lib/actions/reply-to-email-action.d.ts +16 -0
  80. package/dist/lib/actions/reply-to-email-action.d.ts.map +1 -0
  81. package/dist/lib/actions/reply-to-email-action.js +202 -0
  82. package/dist/lib/actions/reply-to-email-action.js.map +1 -0
  83. package/dist/lib/actions/request-approval-in-email.d.ts +15 -0
  84. package/dist/lib/actions/request-approval-in-email.d.ts.map +1 -0
  85. package/dist/lib/actions/request-approval-in-email.js +174 -0
  86. package/dist/lib/actions/request-approval-in-email.js.map +1 -0
  87. package/dist/lib/actions/search-email-action.d.ts +22 -0
  88. package/dist/lib/actions/search-email-action.d.ts.map +1 -0
  89. package/dist/lib/actions/search-email-action.js +179 -0
  90. package/dist/lib/actions/search-email-action.js.map +1 -0
  91. package/dist/lib/actions/send-draft-action.d.ts +7 -0
  92. package/dist/lib/actions/send-draft-action.d.ts.map +1 -0
  93. package/dist/lib/actions/send-draft-action.js +57 -0
  94. package/dist/lib/actions/send-draft-action.js.map +1 -0
  95. package/dist/lib/actions/send-email-action.d.ts +18 -0
  96. package/dist/lib/actions/send-email-action.d.ts.map +1 -0
  97. package/dist/lib/actions/send-email-action.js +196 -0
  98. package/dist/lib/actions/send-email-action.js.map +1 -0
  99. package/dist/lib/actions/stop-watch-action.d.ts +5 -0
  100. package/dist/lib/actions/stop-watch-action.d.ts.map +1 -0
  101. package/dist/lib/actions/stop-watch-action.js +41 -0
  102. package/dist/lib/actions/stop-watch-action.js.map +1 -0
  103. package/dist/lib/actions/update-draft-action.d.ts +17 -0
  104. package/dist/lib/actions/update-draft-action.d.ts.map +1 -0
  105. package/dist/lib/actions/update-draft-action.js +193 -0
  106. package/dist/lib/actions/update-draft-action.js.map +1 -0
  107. package/dist/lib/auth.d.ts +12 -0
  108. package/dist/lib/auth.d.ts.map +1 -0
  109. package/dist/lib/auth.js +108 -0
  110. package/dist/lib/auth.js.map +1 -0
  111. package/dist/lib/common/data.d.ts +132 -0
  112. package/dist/lib/common/data.d.ts.map +1 -0
  113. package/dist/lib/common/data.js +209 -0
  114. package/dist/lib/common/data.js.map +1 -0
  115. package/dist/lib/common/mime.d.ts +29 -0
  116. package/dist/lib/common/mime.d.ts.map +1 -0
  117. package/dist/lib/common/mime.js +59 -0
  118. package/dist/lib/common/mime.js.map +1 -0
  119. package/dist/lib/common/models.d.ts +86 -0
  120. package/dist/lib/common/models.d.ts.map +1 -0
  121. package/dist/lib/common/models.js +26 -0
  122. package/dist/lib/common/models.js.map +1 -0
  123. package/dist/lib/common/props.d.ts +28 -0
  124. package/dist/lib/common/props.d.ts.map +1 -0
  125. package/dist/lib/common/props.js +231 -0
  126. package/dist/lib/common/props.js.map +1 -0
  127. package/dist/lib/output-schemas.d.ts +29 -0
  128. package/dist/lib/output-schemas.d.ts.map +1 -0
  129. package/dist/lib/output-schemas.js +1029 -0
  130. package/dist/lib/output-schemas.js.map +1 -0
  131. package/dist/lib/triggers/new-attachment.d.ts +144 -0
  132. package/dist/lib/triggers/new-attachment.d.ts.map +1 -0
  133. package/dist/lib/triggers/new-attachment.js +150 -0
  134. package/dist/lib/triggers/new-attachment.js.map +1 -0
  135. package/dist/lib/triggers/new-conversation.d.ts +59 -0
  136. package/dist/lib/triggers/new-conversation.d.ts.map +1 -0
  137. package/dist/lib/triggers/new-conversation.js +308 -0
  138. package/dist/lib/triggers/new-conversation.js.map +1 -0
  139. package/dist/lib/triggers/new-email.d.ts +52 -0
  140. package/dist/lib/triggers/new-email.d.ts.map +1 -0
  141. package/dist/lib/triggers/new-email.js +135 -0
  142. package/dist/lib/triggers/new-email.js.map +1 -0
  143. package/dist/lib/triggers/new-label.d.ts +15 -0
  144. package/dist/lib/triggers/new-label.d.ts.map +1 -0
  145. package/dist/lib/triggers/new-label.js +82 -0
  146. package/dist/lib/triggers/new-label.js.map +1 -0
  147. package/dist/lib/triggers/new-labeled-email.d.ts +35 -0
  148. package/dist/lib/triggers/new-labeled-email.d.ts.map +1 -0
  149. package/dist/lib/triggers/new-labeled-email.js +147 -0
  150. package/dist/lib/triggers/new-labeled-email.js.map +1 -0
  151. package/package.json +53 -3
  152. package/src/index.ts +107 -0
  153. package/src/lib/actions/ai-get-message-action.ts +20 -0
  154. package/src/lib/actions/ai-reply-to-thread-action.ts +20 -0
  155. package/src/lib/actions/ai-search-email-action.ts +21 -0
  156. package/src/lib/actions/ai-send-email-action.ts +20 -0
  157. package/src/lib/actions/create-draft-action.ts +148 -0
  158. package/src/lib/actions/create-draft-reply-action.ts +314 -0
  159. package/src/lib/actions/delete-draft-action.ts +57 -0
  160. package/src/lib/actions/forward-message-action.ts +159 -0
  161. package/src/lib/actions/get-attachment-action.ts +83 -0
  162. package/src/lib/actions/get-draft-action.ts +53 -0
  163. package/src/lib/actions/get-label-action.ts +53 -0
  164. package/src/lib/actions/get-mail-action.ts +52 -0
  165. package/src/lib/actions/get-profile-action.ts +39 -0
  166. package/src/lib/actions/get-thread-action.ts +47 -0
  167. package/src/lib/actions/list-drafts-action.ts +72 -0
  168. package/src/lib/actions/list-history-action.ts +83 -0
  169. package/src/lib/actions/list-labels-action.ts +43 -0
  170. package/src/lib/actions/list-threads-action.ts +89 -0
  171. package/src/lib/actions/reply-to-email-action.ts +228 -0
  172. package/src/lib/actions/request-approval-in-email.ts +197 -0
  173. package/src/lib/actions/search-email-action.ts +219 -0
  174. package/src/lib/actions/send-draft-action.ts +54 -0
  175. package/src/lib/actions/send-email-action.ts +213 -0
  176. package/src/lib/actions/stop-watch-action.ts +37 -0
  177. package/src/lib/actions/update-draft-action.ts +211 -0
  178. package/src/lib/auth.ts +116 -0
  179. package/src/lib/common/data.ts +268 -0
  180. package/src/lib/common/mime.ts +82 -0
  181. package/src/lib/common/models.ts +91 -0
  182. package/src/lib/common/props.ts +262 -0
  183. package/src/lib/output-schemas.ts +1061 -0
  184. package/src/lib/triggers/new-attachment.ts +203 -0
  185. package/src/lib/triggers/new-conversation.ts +413 -0
  186. package/src/lib/triggers/new-email.ts +173 -0
  187. package/src/lib/triggers/new-label.ts +83 -0
  188. package/src/lib/triggers/new-labeled-email.ts +197 -0
@@ -0,0 +1,53 @@
1
+ import { createAction, Property } from '@agnocon/pieces-framework';
2
+ import { gmailAuth, createGoogleClient } from '../auth';
3
+ import { gmail as googleGmail } from '@googleapis/gmail';
4
+ import { gmailGetLabelActionOutputSchema } from '../output-schemas';
5
+
6
+ export const gmailGetLabelAction = createAction({
7
+ auth: gmailAuth,
8
+ name: 'gmail_get_label',
9
+ displayName: 'Get Label',
10
+ description:
11
+ 'Get a single label by its ID, including message and thread counts.',
12
+ audience: 'ai',
13
+ aiMetadata: {
14
+ description:
15
+ 'Fetches a single label by its label ID, returning its name, type, visibility, color, and message/thread counts. Use this to inspect a label or read how many messages carry it; obtain the label ID from List Labels. Idempotent: a read-only lookup that does not modify the mailbox.',
16
+ idempotent: true,
17
+ },
18
+ props: {
19
+ label_id: Property.ShortText({
20
+ displayName: 'Label ID',
21
+ description: 'The ID of the label to read (obtain from List Labels).',
22
+ required: true,
23
+ }),
24
+ },
25
+ outputSchema: gmailGetLabelActionOutputSchema,
26
+ async run(context) {
27
+ const authClient = await createGoogleClient(context.auth);
28
+ const gmail = googleGmail({ version: 'v1', auth: authClient });
29
+
30
+ try {
31
+ const response = await gmail.users.labels.get({
32
+ userId: 'me',
33
+ id: context.propsValue.label_id,
34
+ });
35
+ return response.data;
36
+ } catch (error: any) {
37
+ if (error.code === 403) {
38
+ throw new Error(
39
+ 'Insufficient permissions to read the label. Ensure the gmail.readonly scope is granted.'
40
+ );
41
+ } else if (error.code === 404) {
42
+ throw new Error(
43
+ `Label not found: "${context.propsValue.label_id}". Use List Labels to find a valid label ID.`
44
+ );
45
+ } else if (error.code === 429) {
46
+ throw new Error(
47
+ 'Gmail API rate limit exceeded. Please try again later.'
48
+ );
49
+ }
50
+ throw new Error(`Failed to get label: ${error.message}`);
51
+ }
52
+ },
53
+ });
@@ -0,0 +1,52 @@
1
+ import { createAction, Property } from '@agnocon/pieces-framework';
2
+ import { gmailAuth, createGoogleClient } from '../auth';
3
+ import { gmail as googleGmail } from '@googleapis/gmail';
4
+ import { convertAttachment, parseStream } from '../common/data';
5
+ import { gmailGetMailActionOutputSchema } from '../output-schemas';
6
+
7
+ export const gmailGetEmailAction = createAction({
8
+ auth: gmailAuth,
9
+ name: 'gmail_get_mail',
10
+ description: 'Get an email via Id.',
11
+ audience: 'human',
12
+ aiMetadata: {
13
+ description:
14
+ 'Fetches a single email by its Gmail message ID and returns its parsed contents, including headers, body, and decoded attachments. Use this to read the full details of a specific known message, typically after a trigger or search yields its ID. Idempotent: a read-only lookup that does not modify the mailbox.',
15
+ idempotent: true,
16
+ },
17
+ displayName: 'Get Email',
18
+ props: {
19
+ message_id: Property.ShortText({
20
+ displayName: 'Message ID',
21
+ description: 'The messageId of the mail to read.',
22
+ required: true,
23
+ }),
24
+ },
25
+ outputSchema: gmailGetMailActionOutputSchema,
26
+ async run(context) {
27
+ const authClient = await createGoogleClient(context.auth);
28
+
29
+ const gmail = googleGmail({ version: 'v1', auth: authClient });
30
+
31
+ const rawMailResponse = await gmail.users.messages.get({
32
+ userId: 'me',
33
+ id: context.propsValue.message_id!,
34
+ format: 'raw',
35
+ });
36
+
37
+ const parsedMailResponse = await parseStream(
38
+ Buffer.from(rawMailResponse.data.raw as string, 'base64').toString(
39
+ 'utf-8'
40
+ )
41
+ );
42
+
43
+ return {
44
+ id: context.propsValue.message_id,
45
+ ...parsedMailResponse,
46
+ attachments: await convertAttachment(
47
+ parsedMailResponse.attachments,
48
+ context.files
49
+ ),
50
+ };
51
+ },
52
+ });
@@ -0,0 +1,39 @@
1
+ import { createAction } from '@agnocon/pieces-framework';
2
+ import { gmailAuth, createGoogleClient } from '../auth';
3
+ import { gmail as googleGmail } from '@googleapis/gmail';
4
+ import { gmailGetProfileActionOutputSchema } from '../output-schemas';
5
+
6
+ export const gmailGetProfileAction = createAction({
7
+ auth: gmailAuth,
8
+ name: 'gmail_get_profile',
9
+ displayName: 'Get Profile',
10
+ description: 'Get the connected mailbox profile.',
11
+ audience: 'ai',
12
+ aiMetadata: {
13
+ description:
14
+ 'Returns the connected mailbox profile: the account email address, total message and thread counts, and the current history ID. Use this to confirm which account is connected or to obtain the starting history ID for List History. Idempotent: a read-only lookup that does not modify the mailbox.',
15
+ idempotent: true,
16
+ },
17
+ props: {},
18
+ outputSchema: gmailGetProfileActionOutputSchema,
19
+ async run(context) {
20
+ const authClient = await createGoogleClient(context.auth);
21
+ const gmail = googleGmail({ version: 'v1', auth: authClient });
22
+
23
+ try {
24
+ const response = await gmail.users.getProfile({ userId: 'me' });
25
+ return response.data;
26
+ } catch (error: any) {
27
+ if (error.code === 403) {
28
+ throw new Error(
29
+ 'Insufficient permissions to read the profile. Ensure a read scope (e.g. gmail.readonly) is granted.'
30
+ );
31
+ } else if (error.code === 429) {
32
+ throw new Error(
33
+ 'Gmail API rate limit exceeded. Please try again later.'
34
+ );
35
+ }
36
+ throw new Error(`Failed to get profile: ${error.message}`);
37
+ }
38
+ },
39
+ });
@@ -0,0 +1,47 @@
1
+ import { createAction, Property } from '@agnocon/pieces-framework';
2
+ import { GmailRequests } from '../common/data';
3
+ import { GmailMessageFormat } from '../common/models';
4
+ import { gmailAuth, getAccessToken } from '../auth';
5
+ import { gmailGetThreadActionOutputSchema } from '../output-schemas';
6
+
7
+ export const gmailGetThread = createAction({
8
+ auth: gmailAuth,
9
+ name: 'gmail_get_thread',
10
+ description: 'Get a thread from your Gmail account via Id',
11
+ displayName: 'Get Thread',
12
+ audience: 'ai',
13
+ aiMetadata: {
14
+ description:
15
+ 'Fetches an entire email conversation by its Gmail thread ID, returning every message in the thread. Use this to read a full conversation or to discover the message IDs within a thread before replying; obtain the thread ID from Search Email or List Threads. Idempotent: a read-only lookup that does not modify the mailbox.',
16
+ idempotent: true,
17
+ },
18
+ props: {
19
+ thread_id: Property.ShortText({
20
+ displayName: 'Thread ID',
21
+ description: 'The thread Id of the mail to read',
22
+ required: true,
23
+ }),
24
+ format: Property.StaticDropdown<GmailMessageFormat>({
25
+ displayName: 'Format',
26
+ description: 'Format of the mail',
27
+ required: false,
28
+ defaultValue: 'full',
29
+ options: {
30
+ disabled: false,
31
+ options: [
32
+ { value: GmailMessageFormat.MINIMAL, label: 'Minimal' },
33
+ { value: GmailMessageFormat.FULL, label: 'Full' },
34
+ { value: GmailMessageFormat.RAW, label: 'Raw' },
35
+ { value: GmailMessageFormat.METADATA, label: 'Metadata' },
36
+ ],
37
+ },
38
+ }),
39
+ },
40
+ outputSchema: gmailGetThreadActionOutputSchema,
41
+ run: async ({ auth, propsValue: { format, thread_id } }) =>
42
+ await GmailRequests.getThread({
43
+ access_token: await getAccessToken(auth),
44
+ thread_id,
45
+ format: format ?? GmailMessageFormat.FULL,
46
+ }),
47
+ });
@@ -0,0 +1,72 @@
1
+ import { createAction, Property } from '@agnocon/pieces-framework';
2
+ import { gmailAuth, createGoogleClient } from '../auth';
3
+ import { gmail as googleGmail } from '@googleapis/gmail';
4
+ import { gmailListDraftsActionOutputSchema } from '../output-schemas';
5
+
6
+ export const gmailListDraftsAction = createAction({
7
+ auth: gmailAuth,
8
+ name: 'gmail_list_drafts',
9
+ displayName: 'List Drafts',
10
+ description: 'List draft emails in the mailbox.',
11
+ audience: 'ai',
12
+ aiMetadata: {
13
+ description:
14
+ 'Lists draft emails in the connected mailbox, returning each draft ID and its associated message. This is the resolver for obtaining draft IDs used by Get Draft, Update Draft, Send Draft, and Delete Draft. Optionally narrow with a Gmail search query and bound with Max Results. Idempotent: a read-only listing that does not modify the mailbox.',
15
+ idempotent: true,
16
+ },
17
+ props: {
18
+ query: Property.ShortText({
19
+ displayName: 'Search Query',
20
+ description:
21
+ 'Optional Gmail search query to filter drafts (e.g. "subject:invoice").',
22
+ required: false,
23
+ }),
24
+ max_results: Property.Number({
25
+ displayName: 'Max Results',
26
+ description: 'Maximum number of drafts to return (1-500).',
27
+ required: false,
28
+ defaultValue: 20,
29
+ }),
30
+ },
31
+ outputSchema: gmailListDraftsActionOutputSchema,
32
+ async run(context) {
33
+ const authClient = await createGoogleClient(context.auth);
34
+ const gmail = googleGmail({ version: 'v1', auth: authClient });
35
+
36
+ const maxResults = Math.min(
37
+ Math.max(context.propsValue.max_results || 20, 1),
38
+ 500
39
+ );
40
+
41
+ try {
42
+ const response = await gmail.users.drafts.list({
43
+ userId: 'me',
44
+ maxResults,
45
+ ...(context.propsValue.query?.trim()
46
+ ? { q: context.propsValue.query.trim() }
47
+ : {}),
48
+ });
49
+
50
+ const drafts = response.data.drafts || [];
51
+ return {
52
+ drafts,
53
+ count: drafts.length,
54
+ resultSizeEstimate: response.data.resultSizeEstimate,
55
+ ...(response.data.nextPageToken
56
+ ? { nextPageToken: response.data.nextPageToken }
57
+ : {}),
58
+ };
59
+ } catch (error: any) {
60
+ if (error.code === 403) {
61
+ throw new Error(
62
+ 'Insufficient permissions to list drafts. Ensure the gmail.readonly scope is granted.'
63
+ );
64
+ } else if (error.code === 429) {
65
+ throw new Error(
66
+ 'Gmail API rate limit exceeded. Please try again later.'
67
+ );
68
+ }
69
+ throw new Error(`Failed to list drafts: ${error.message}`);
70
+ }
71
+ },
72
+ });
@@ -0,0 +1,83 @@
1
+ import { createAction, Property } from '@agnocon/pieces-framework';
2
+ import { gmailAuth, createGoogleClient } from '../auth';
3
+ import { gmail as googleGmail } from '@googleapis/gmail';
4
+ import { gmailListHistoryActionOutputSchema } from '../output-schemas';
5
+
6
+ export const gmailListHistoryAction = createAction({
7
+ auth: gmailAuth,
8
+ name: 'gmail_list_history',
9
+ displayName: 'List History',
10
+ description: 'List mailbox changes since a given history ID.',
11
+ audience: 'ai',
12
+ aiMetadata: {
13
+ description:
14
+ 'Returns the incremental change log (messages added, deleted, or relabeled) since a given starting history ID. Use this to detect what changed in the mailbox since a previous checkpoint; obtain the starting history ID from Get Profile (or a prior run). Idempotent: a read-only listing that does not modify the mailbox.',
15
+ idempotent: true,
16
+ },
17
+ props: {
18
+ start_history_id: Property.ShortText({
19
+ displayName: 'Start History ID',
20
+ description:
21
+ 'Return changes after this history ID (obtain from Get Profile or a previous history result).',
22
+ required: true,
23
+ }),
24
+ history_types: Property.StaticMultiSelectDropdown({
25
+ displayName: 'History Types',
26
+ description: 'Limit results to these change types (leave empty for all).',
27
+ required: false,
28
+ options: {
29
+ disabled: false,
30
+ options: [
31
+ { label: 'Message Added', value: 'messageAdded' },
32
+ { label: 'Message Deleted', value: 'messageDeleted' },
33
+ { label: 'Label Added', value: 'labelAdded' },
34
+ { label: 'Label Removed', value: 'labelRemoved' },
35
+ ],
36
+ },
37
+ }),
38
+ max_results: Property.Number({
39
+ displayName: 'Max Results',
40
+ description: 'Maximum number of history records to return (1-500).',
41
+ required: false,
42
+ defaultValue: 100,
43
+ }),
44
+ },
45
+ outputSchema: gmailListHistoryActionOutputSchema,
46
+ async run(context) {
47
+ const authClient = await createGoogleClient(context.auth);
48
+ const gmail = googleGmail({ version: 'v1', auth: authClient });
49
+
50
+ const maxResults = Math.min(
51
+ Math.max(context.propsValue.max_results || 100, 1),
52
+ 500
53
+ );
54
+ const historyTypes = context.propsValue.history_types as
55
+ | string[]
56
+ | undefined;
57
+
58
+ try {
59
+ const response = await gmail.users.history.list({
60
+ userId: 'me',
61
+ startHistoryId: context.propsValue.start_history_id,
62
+ maxResults,
63
+ ...(historyTypes && historyTypes.length > 0 ? { historyTypes } : {}),
64
+ });
65
+ return response.data;
66
+ } catch (error: any) {
67
+ if (error.code === 403) {
68
+ throw new Error(
69
+ 'Insufficient permissions to read history. Ensure the gmail.readonly scope is granted.'
70
+ );
71
+ } else if (error.code === 404) {
72
+ throw new Error(
73
+ 'The start history ID is too old or invalid. Fetch a fresh history ID from Get Profile.'
74
+ );
75
+ } else if (error.code === 429) {
76
+ throw new Error(
77
+ 'Gmail API rate limit exceeded. Please try again later.'
78
+ );
79
+ }
80
+ throw new Error(`Failed to list history: ${error.message}`);
81
+ }
82
+ },
83
+ });
@@ -0,0 +1,43 @@
1
+ import { createAction } from '@agnocon/pieces-framework';
2
+ import { gmailAuth, createGoogleClient } from '../auth';
3
+ import { gmail as googleGmail } from '@googleapis/gmail';
4
+ import { gmailListLabelsActionOutputSchema } from '../output-schemas';
5
+
6
+ export const gmailListLabelsAction = createAction({
7
+ auth: gmailAuth,
8
+ name: 'gmail_list_labels',
9
+ displayName: 'List Labels',
10
+ description: 'List all labels in the mailbox.',
11
+ audience: 'ai',
12
+ aiMetadata: {
13
+ description:
14
+ 'Lists every label in the mailbox (both system labels like INBOX/UNREAD/STARRED and user-created labels) with their IDs, names, and types. This is the primary resolver for label IDs — look up a label ID by name here before passing it to Get Label or any label-aware action. Idempotent: a read-only listing that does not modify the mailbox.',
15
+ idempotent: true,
16
+ },
17
+ props: {},
18
+ outputSchema: gmailListLabelsActionOutputSchema,
19
+ async run(context) {
20
+ const authClient = await createGoogleClient(context.auth);
21
+ const gmail = googleGmail({ version: 'v1', auth: authClient });
22
+
23
+ try {
24
+ const response = await gmail.users.labels.list({ userId: 'me' });
25
+ const labels = response.data.labels || [];
26
+ return {
27
+ labels,
28
+ count: labels.length,
29
+ };
30
+ } catch (error: any) {
31
+ if (error.code === 403) {
32
+ throw new Error(
33
+ 'Insufficient permissions to list labels. Ensure the gmail.readonly scope is granted.'
34
+ );
35
+ } else if (error.code === 429) {
36
+ throw new Error(
37
+ 'Gmail API rate limit exceeded. Please try again later.'
38
+ );
39
+ }
40
+ throw new Error(`Failed to list labels: ${error.message}`);
41
+ }
42
+ },
43
+ });
@@ -0,0 +1,89 @@
1
+ import { createAction, Property } from '@agnocon/pieces-framework';
2
+ import { gmailAuth, createGoogleClient } from '../auth';
3
+ import { gmail as googleGmail } from '@googleapis/gmail';
4
+ import { gmailListThreadsActionOutputSchema } from '../output-schemas';
5
+
6
+ export const gmailListThreadsAction = createAction({
7
+ auth: gmailAuth,
8
+ name: 'gmail_list_threads',
9
+ displayName: 'List Threads',
10
+ description: 'List email conversation threads in the mailbox.',
11
+ audience: 'ai',
12
+ aiMetadata: {
13
+ description:
14
+ 'Lists email conversation threads matching an optional Gmail search query and label filter, returning each thread ID and snippet. This is the resolver for obtaining thread IDs used by Get Thread and Reply to Thread. Resolve label IDs with List Labels. Idempotent: a read-only listing that does not modify the mailbox.',
15
+ idempotent: true,
16
+ },
17
+ props: {
18
+ query: Property.ShortText({
19
+ displayName: 'Search Query',
20
+ description:
21
+ 'Optional Gmail search query to filter threads (e.g. "from:boss@example.com is:unread").',
22
+ required: false,
23
+ }),
24
+ label_ids: Property.Array({
25
+ displayName: 'Label IDs',
26
+ description:
27
+ 'Optional list of label IDs to filter by (resolve via List Labels; system labels like INBOX, UNREAD are valid).',
28
+ required: false,
29
+ }),
30
+ include_spam_trash: Property.Checkbox({
31
+ displayName: 'Include Spam & Trash',
32
+ description: 'Include threads from Spam and Trash in the results.',
33
+ required: false,
34
+ defaultValue: false,
35
+ }),
36
+ max_results: Property.Number({
37
+ displayName: 'Max Results',
38
+ description: 'Maximum number of threads to return (1-500).',
39
+ required: false,
40
+ defaultValue: 20,
41
+ }),
42
+ },
43
+ outputSchema: gmailListThreadsActionOutputSchema,
44
+ async run(context) {
45
+ const authClient = await createGoogleClient(context.auth);
46
+ const gmail = googleGmail({ version: 'v1', auth: authClient });
47
+
48
+ const maxResults = Math.min(
49
+ Math.max(context.propsValue.max_results || 20, 1),
50
+ 500
51
+ );
52
+ const labelIds = (
53
+ context.propsValue.label_ids as string[] | undefined
54
+ )?.filter((id) => id !== '');
55
+
56
+ try {
57
+ const response = await gmail.users.threads.list({
58
+ userId: 'me',
59
+ maxResults,
60
+ includeSpamTrash: context.propsValue.include_spam_trash,
61
+ ...(context.propsValue.query?.trim()
62
+ ? { q: context.propsValue.query.trim() }
63
+ : {}),
64
+ ...(labelIds && labelIds.length > 0 ? { labelIds } : {}),
65
+ });
66
+
67
+ const threads = response.data.threads || [];
68
+ return {
69
+ threads,
70
+ count: threads.length,
71
+ resultSizeEstimate: response.data.resultSizeEstimate,
72
+ ...(response.data.nextPageToken
73
+ ? { nextPageToken: response.data.nextPageToken }
74
+ : {}),
75
+ };
76
+ } catch (error: any) {
77
+ if (error.code === 403) {
78
+ throw new Error(
79
+ 'Insufficient permissions to list threads. Ensure the gmail.readonly scope is granted.'
80
+ );
81
+ } else if (error.code === 429) {
82
+ throw new Error(
83
+ 'Gmail API rate limit exceeded. Please try again later.'
84
+ );
85
+ }
86
+ throw new Error(`Failed to list threads: ${error.message}`);
87
+ }
88
+ },
89
+ });