@divyacon/piece-google-docs 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 (243) hide show
  1. package/LICENSE.MIT-AP +24 -0
  2. package/dist/index.d.ts +6 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +128 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/lib/actions/append-text.d.ts +8 -0
  7. package/dist/lib/actions/append-text.d.ts.map +1 -0
  8. package/dist/lib/actions/append-text.js +40 -0
  9. package/dist/lib/actions/append-text.js.map +1 -0
  10. package/dist/lib/actions/batch-update.action.d.ts +8 -0
  11. package/dist/lib/actions/batch-update.action.d.ts.map +1 -0
  12. package/dist/lib/actions/batch-update.action.js +63 -0
  13. package/dist/lib/actions/batch-update.action.js.map +1 -0
  14. package/dist/lib/actions/copy-document.action.d.ts +12 -0
  15. package/dist/lib/actions/copy-document.action.d.ts.map +1 -0
  16. package/dist/lib/actions/copy-document.action.js +72 -0
  17. package/dist/lib/actions/copy-document.action.js.map +1 -0
  18. package/dist/lib/actions/create-and-populate-table.action.d.ts +8 -0
  19. package/dist/lib/actions/create-and-populate-table.action.d.ts.map +1 -0
  20. package/dist/lib/actions/create-and-populate-table.action.js +138 -0
  21. package/dist/lib/actions/create-and-populate-table.action.js.map +1 -0
  22. package/dist/lib/actions/create-document-based-on-template.action.d.ts +10 -0
  23. package/dist/lib/actions/create-document-based-on-template.action.d.ts.map +1 -0
  24. package/dist/lib/actions/create-document-based-on-template.action.js +107 -0
  25. package/dist/lib/actions/create-document-based-on-template.action.js.map +1 -0
  26. package/dist/lib/actions/create-document-from-markdown.action.d.ts +8 -0
  27. package/dist/lib/actions/create-document-from-markdown.action.d.ts.map +1 -0
  28. package/dist/lib/actions/create-document-from-markdown.action.js +69 -0
  29. package/dist/lib/actions/create-document-from-markdown.action.js.map +1 -0
  30. package/dist/lib/actions/create-document.d.ts +8 -0
  31. package/dist/lib/actions/create-document.d.ts.map +1 -0
  32. package/dist/lib/actions/create-document.js +35 -0
  33. package/dist/lib/actions/create-document.js.map +1 -0
  34. package/dist/lib/actions/create-footer.action.d.ts +8 -0
  35. package/dist/lib/actions/create-footer.action.d.ts.map +1 -0
  36. package/dist/lib/actions/create-footer.action.js +66 -0
  37. package/dist/lib/actions/create-footer.action.js.map +1 -0
  38. package/dist/lib/actions/create-footnote.action.d.ts +8 -0
  39. package/dist/lib/actions/create-footnote.action.d.ts.map +1 -0
  40. package/dist/lib/actions/create-footnote.action.js +58 -0
  41. package/dist/lib/actions/create-footnote.action.js.map +1 -0
  42. package/dist/lib/actions/create-header.action.d.ts +8 -0
  43. package/dist/lib/actions/create-header.action.d.ts.map +1 -0
  44. package/dist/lib/actions/create-header.action.js +66 -0
  45. package/dist/lib/actions/create-header.action.js.map +1 -0
  46. package/dist/lib/actions/create-named-range.action.d.ts +10 -0
  47. package/dist/lib/actions/create-named-range.action.d.ts.map +1 -0
  48. package/dist/lib/actions/create-named-range.action.js +74 -0
  49. package/dist/lib/actions/create-named-range.action.js.map +1 -0
  50. package/dist/lib/actions/create-paragraph-bullets.action.d.ts +10 -0
  51. package/dist/lib/actions/create-paragraph-bullets.action.d.ts.map +1 -0
  52. package/dist/lib/actions/create-paragraph-bullets.action.js +98 -0
  53. package/dist/lib/actions/create-paragraph-bullets.action.js.map +1 -0
  54. package/dist/lib/actions/create-text-document.action.d.ts +8 -0
  55. package/dist/lib/actions/create-text-document.action.d.ts.map +1 -0
  56. package/dist/lib/actions/create-text-document.action.js +42 -0
  57. package/dist/lib/actions/create-text-document.action.js.map +1 -0
  58. package/dist/lib/actions/delete-content-range.action.d.ts +9 -0
  59. package/dist/lib/actions/delete-content-range.action.d.ts.map +1 -0
  60. package/dist/lib/actions/delete-content-range.action.js +64 -0
  61. package/dist/lib/actions/delete-content-range.action.js.map +1 -0
  62. package/dist/lib/actions/delete-footer.action.d.ts +8 -0
  63. package/dist/lib/actions/delete-footer.action.d.ts.map +1 -0
  64. package/dist/lib/actions/delete-footer.action.js +56 -0
  65. package/dist/lib/actions/delete-footer.action.js.map +1 -0
  66. package/dist/lib/actions/delete-header.action.d.ts +8 -0
  67. package/dist/lib/actions/delete-header.action.d.ts.map +1 -0
  68. package/dist/lib/actions/delete-header.action.js +56 -0
  69. package/dist/lib/actions/delete-header.action.js.map +1 -0
  70. package/dist/lib/actions/delete-named-range.action.d.ts +9 -0
  71. package/dist/lib/actions/delete-named-range.action.d.ts.map +1 -0
  72. package/dist/lib/actions/delete-named-range.action.js +69 -0
  73. package/dist/lib/actions/delete-named-range.action.js.map +1 -0
  74. package/dist/lib/actions/delete-paragraph-bullets.action.d.ts +9 -0
  75. package/dist/lib/actions/delete-paragraph-bullets.action.d.ts.map +1 -0
  76. package/dist/lib/actions/delete-paragraph-bullets.action.js +66 -0
  77. package/dist/lib/actions/delete-paragraph-bullets.action.js.map +1 -0
  78. package/dist/lib/actions/delete-table-column.action.d.ts +10 -0
  79. package/dist/lib/actions/delete-table-column.action.d.ts.map +1 -0
  80. package/dist/lib/actions/delete-table-column.action.js +72 -0
  81. package/dist/lib/actions/delete-table-column.action.js.map +1 -0
  82. package/dist/lib/actions/delete-table-row.action.d.ts +10 -0
  83. package/dist/lib/actions/delete-table-row.action.d.ts.map +1 -0
  84. package/dist/lib/actions/delete-table-row.action.js +72 -0
  85. package/dist/lib/actions/delete-table-row.action.js.map +1 -0
  86. package/dist/lib/actions/export-as-pdf.action.d.ts +7 -0
  87. package/dist/lib/actions/export-as-pdf.action.d.ts.map +1 -0
  88. package/dist/lib/actions/export-as-pdf.action.js +61 -0
  89. package/dist/lib/actions/export-as-pdf.action.js.map +1 -0
  90. package/dist/lib/actions/find-document.d.ts +16 -0
  91. package/dist/lib/actions/find-document.d.ts.map +1 -0
  92. package/dist/lib/actions/find-document.js +127 -0
  93. package/dist/lib/actions/find-document.js.map +1 -0
  94. package/dist/lib/actions/get-document-end-index.action.d.ts +7 -0
  95. package/dist/lib/actions/get-document-end-index.action.d.ts.map +1 -0
  96. package/dist/lib/actions/get-document-end-index.action.js +54 -0
  97. package/dist/lib/actions/get-document-end-index.action.js.map +1 -0
  98. package/dist/lib/actions/get-document-plaintext.action.d.ts +7 -0
  99. package/dist/lib/actions/get-document-plaintext.action.d.ts.map +1 -0
  100. package/dist/lib/actions/get-document-plaintext.action.js +76 -0
  101. package/dist/lib/actions/get-document-plaintext.action.js.map +1 -0
  102. package/dist/lib/actions/get-document.action.d.ts +7 -0
  103. package/dist/lib/actions/get-document.action.d.ts.map +1 -0
  104. package/dist/lib/actions/get-document.action.js +45 -0
  105. package/dist/lib/actions/get-document.action.js.map +1 -0
  106. package/dist/lib/actions/insert-image-in-table-cell.action.d.ts +13 -0
  107. package/dist/lib/actions/insert-image-in-table-cell.action.d.ts.map +1 -0
  108. package/dist/lib/actions/insert-image-in-table-cell.action.js +128 -0
  109. package/dist/lib/actions/insert-image-in-table-cell.action.js.map +1 -0
  110. package/dist/lib/actions/insert-inline-image.action.d.ts +11 -0
  111. package/dist/lib/actions/insert-inline-image.action.d.ts.map +1 -0
  112. package/dist/lib/actions/insert-inline-image.action.js +84 -0
  113. package/dist/lib/actions/insert-inline-image.action.js.map +1 -0
  114. package/dist/lib/actions/insert-page-break.action.d.ts +8 -0
  115. package/dist/lib/actions/insert-page-break.action.d.ts.map +1 -0
  116. package/dist/lib/actions/insert-page-break.action.js +60 -0
  117. package/dist/lib/actions/insert-page-break.action.js.map +1 -0
  118. package/dist/lib/actions/insert-table-column.action.d.ts +11 -0
  119. package/dist/lib/actions/insert-table-column.action.d.ts.map +1 -0
  120. package/dist/lib/actions/insert-table-column.action.js +86 -0
  121. package/dist/lib/actions/insert-table-column.action.js.map +1 -0
  122. package/dist/lib/actions/insert-table-row.action.d.ts +11 -0
  123. package/dist/lib/actions/insert-table-row.action.d.ts.map +1 -0
  124. package/dist/lib/actions/insert-table-row.action.js +86 -0
  125. package/dist/lib/actions/insert-table-row.action.js.map +1 -0
  126. package/dist/lib/actions/insert-table.action.d.ts +10 -0
  127. package/dist/lib/actions/insert-table.action.d.ts.map +1 -0
  128. package/dist/lib/actions/insert-table.action.js +72 -0
  129. package/dist/lib/actions/insert-table.action.js.map +1 -0
  130. package/dist/lib/actions/insert-text-in-table-cell.action.d.ts +11 -0
  131. package/dist/lib/actions/insert-text-in-table-cell.action.d.ts.map +1 -0
  132. package/dist/lib/actions/insert-text-in-table-cell.action.js +115 -0
  133. package/dist/lib/actions/insert-text-in-table-cell.action.js.map +1 -0
  134. package/dist/lib/actions/insert-text.action.d.ts +9 -0
  135. package/dist/lib/actions/insert-text.action.d.ts.map +1 -0
  136. package/dist/lib/actions/insert-text.action.js +66 -0
  137. package/dist/lib/actions/insert-text.action.js.map +1 -0
  138. package/dist/lib/actions/read-document.action.d.ts +7 -0
  139. package/dist/lib/actions/read-document.action.d.ts.map +1 -0
  140. package/dist/lib/actions/read-document.action.js +44 -0
  141. package/dist/lib/actions/read-document.action.js.map +1 -0
  142. package/dist/lib/actions/replace-all-text.action.d.ts +10 -0
  143. package/dist/lib/actions/replace-all-text.action.d.ts.map +1 -0
  144. package/dist/lib/actions/replace-all-text.action.js +92 -0
  145. package/dist/lib/actions/replace-all-text.action.js.map +1 -0
  146. package/dist/lib/actions/replace-body-with-markdown.action.d.ts +8 -0
  147. package/dist/lib/actions/replace-body-with-markdown.action.d.ts.map +1 -0
  148. package/dist/lib/actions/replace-body-with-markdown.action.js +79 -0
  149. package/dist/lib/actions/replace-body-with-markdown.action.js.map +1 -0
  150. package/dist/lib/actions/replace-image.action.d.ts +9 -0
  151. package/dist/lib/actions/replace-image.action.d.ts.map +1 -0
  152. package/dist/lib/actions/replace-image.action.js +65 -0
  153. package/dist/lib/actions/replace-image.action.js.map +1 -0
  154. package/dist/lib/actions/replace-section-with-markdown.action.d.ts +10 -0
  155. package/dist/lib/actions/replace-section-with-markdown.action.d.ts.map +1 -0
  156. package/dist/lib/actions/replace-section-with-markdown.action.js +106 -0
  157. package/dist/lib/actions/replace-section-with-markdown.action.js.map +1 -0
  158. package/dist/lib/actions/search-documents.action.d.ts +11 -0
  159. package/dist/lib/actions/search-documents.action.d.ts.map +1 -0
  160. package/dist/lib/actions/search-documents.action.js +121 -0
  161. package/dist/lib/actions/search-documents.action.js.map +1 -0
  162. package/dist/lib/actions/unmerge-table-cells.action.d.ts +12 -0
  163. package/dist/lib/actions/unmerge-table-cells.action.d.ts.map +1 -0
  164. package/dist/lib/actions/unmerge-table-cells.action.js +94 -0
  165. package/dist/lib/actions/unmerge-table-cells.action.js.map +1 -0
  166. package/dist/lib/actions/update-document-style.action.d.ts +11 -0
  167. package/dist/lib/actions/update-document-style.action.d.ts.map +1 -0
  168. package/dist/lib/actions/update-document-style.action.js +95 -0
  169. package/dist/lib/actions/update-document-style.action.js.map +1 -0
  170. package/dist/lib/actions/update-table-row-style.action.d.ts +10 -0
  171. package/dist/lib/actions/update-table-row-style.action.d.ts.map +1 -0
  172. package/dist/lib/actions/update-table-row-style.action.js +78 -0
  173. package/dist/lib/actions/update-table-row-style.action.js.map +1 -0
  174. package/dist/lib/auth.d.ts +11 -0
  175. package/dist/lib/auth.d.ts.map +1 -0
  176. package/dist/lib/auth.js +92 -0
  177. package/dist/lib/auth.js.map +1 -0
  178. package/dist/lib/common/index.d.ts +11 -0
  179. package/dist/lib/common/index.d.ts.map +1 -0
  180. package/dist/lib/common/index.js +124 -0
  181. package/dist/lib/common/index.js.map +1 -0
  182. package/dist/lib/common/props.d.ts +5 -0
  183. package/dist/lib/common/props.d.ts.map +1 -0
  184. package/dist/lib/common/props.js +53 -0
  185. package/dist/lib/common/props.js.map +1 -0
  186. package/dist/lib/output-schemas.d.ts +43 -0
  187. package/dist/lib/output-schemas.d.ts.map +1 -0
  188. package/dist/lib/output-schemas.js +554 -0
  189. package/dist/lib/output-schemas.js.map +1 -0
  190. package/dist/lib/triggers/new-document.d.ts +35 -0
  191. package/dist/lib/triggers/new-document.d.ts.map +1 -0
  192. package/dist/lib/triggers/new-document.js +104 -0
  193. package/dist/lib/triggers/new-document.js.map +1 -0
  194. package/package.json +47 -3
  195. package/src/index.ts +120 -0
  196. package/src/lib/actions/append-text.ts +37 -0
  197. package/src/lib/actions/batch-update.action.ts +58 -0
  198. package/src/lib/actions/copy-document.action.ts +74 -0
  199. package/src/lib/actions/create-and-populate-table.action.ts +141 -0
  200. package/src/lib/actions/create-document-based-on-template.action.ts +110 -0
  201. package/src/lib/actions/create-document-from-markdown.action.ts +63 -0
  202. package/src/lib/actions/create-document.ts +36 -0
  203. package/src/lib/actions/create-footer.action.ts +59 -0
  204. package/src/lib/actions/create-footnote.action.ts +53 -0
  205. package/src/lib/actions/create-header.action.ts +59 -0
  206. package/src/lib/actions/create-named-range.action.ts +70 -0
  207. package/src/lib/actions/create-paragraph-bullets.action.ts +95 -0
  208. package/src/lib/actions/create-text-document.action.ts +35 -0
  209. package/src/lib/actions/delete-content-range.action.ts +59 -0
  210. package/src/lib/actions/delete-footer.action.ts +51 -0
  211. package/src/lib/actions/delete-header.action.ts +51 -0
  212. package/src/lib/actions/delete-named-range.action.ts +65 -0
  213. package/src/lib/actions/delete-paragraph-bullets.action.ts +62 -0
  214. package/src/lib/actions/delete-table-column.action.ts +67 -0
  215. package/src/lib/actions/delete-table-row.action.ts +67 -0
  216. package/src/lib/actions/export-as-pdf.action.ts +59 -0
  217. package/src/lib/actions/find-document.ts +136 -0
  218. package/src/lib/actions/get-document-end-index.action.ts +47 -0
  219. package/src/lib/actions/get-document-plaintext.action.ts +74 -0
  220. package/src/lib/actions/get-document.action.ts +37 -0
  221. package/src/lib/actions/insert-image-in-table-cell.action.ts +139 -0
  222. package/src/lib/actions/insert-inline-image.action.ts +83 -0
  223. package/src/lib/actions/insert-page-break.action.ts +56 -0
  224. package/src/lib/actions/insert-table-column.action.ts +80 -0
  225. package/src/lib/actions/insert-table-row.action.ts +80 -0
  226. package/src/lib/actions/insert-table.action.ts +68 -0
  227. package/src/lib/actions/insert-text-in-table-cell.action.ts +120 -0
  228. package/src/lib/actions/insert-text.action.ts +62 -0
  229. package/src/lib/actions/read-document.action.ts +40 -0
  230. package/src/lib/actions/replace-all-text.action.ts +95 -0
  231. package/src/lib/actions/replace-body-with-markdown.action.ts +76 -0
  232. package/src/lib/actions/replace-image.action.ts +60 -0
  233. package/src/lib/actions/replace-section-with-markdown.action.ts +104 -0
  234. package/src/lib/actions/search-documents.action.ts +131 -0
  235. package/src/lib/actions/unmerge-table-cells.action.ts +88 -0
  236. package/src/lib/actions/update-document-style.action.ts +93 -0
  237. package/src/lib/actions/update-table-row-style.action.ts +73 -0
  238. package/src/lib/auth.ts +84 -0
  239. package/src/lib/common/index.ts +126 -0
  240. package/src/lib/common/props.ts +55 -0
  241. package/src/lib/output-schemas.ts +593 -0
  242. package/src/lib/triggers/new-document.ts +108 -0
  243. package/README.md +0 -3
@@ -0,0 +1,62 @@
1
+ import { googleDocsAuth, createGoogleClient } from '../auth';
2
+ import { docsCommon } from '../common';
3
+ import { Property, createAction } from '@agnocon/pieces-framework';
4
+ import { docs as googleDocs, docs_v1 } from '@googleapis/docs';
5
+ import { insertTextActionOutputSchema } from '../output-schemas';
6
+
7
+ export const insertText = createAction({
8
+ auth: googleDocsAuth,
9
+ name: 'insert_text',
10
+ displayName: 'Insert Text',
11
+ description: 'Insert text into a Google Docs document at a position or at the end',
12
+ audience: 'ai',
13
+ aiMetadata: {
14
+ description:
15
+ 'Inserts text into a Google Docs document. If "index" is omitted the text is appended to the end of the document body; if "index" is provided the text is inserted at that character index — obtain a valid index from Get Document End Index first (indices cannot be guessed, must fall inside an existing paragraph, and must be below the body end index). Not idempotent: each call inserts the text again.',
16
+ idempotent: false,
17
+ },
18
+ outputSchema: insertTextActionOutputSchema,
19
+ props: {
20
+ documentId: Property.ShortText({
21
+ displayName: 'Document ID',
22
+ description: 'The ID of the document to insert text into.',
23
+ required: true,
24
+ }),
25
+ text: Property.LongText({
26
+ displayName: 'Text',
27
+ description: 'The text to insert.',
28
+ required: true,
29
+ }),
30
+ index: Property.Number({
31
+ displayName: 'Index',
32
+ description:
33
+ 'Character index to insert at. Leave empty to append to the end of the document. Get a valid index from Get Document End Index.',
34
+ required: false,
35
+ }),
36
+ },
37
+ async run(context) {
38
+ const { documentId, text, index } = context.propsValue;
39
+ const authClient = await createGoogleClient(context.auth);
40
+ const docs = googleDocs({ version: 'v1', auth: authClient });
41
+
42
+ const request: docs_v1.Schema$Request =
43
+ index === undefined || index === null
44
+ ? { insertText: { text, endOfSegmentLocation: {} } }
45
+ : { insertText: { text, location: { index } } };
46
+
47
+ try {
48
+ await docs.documents.batchUpdate({
49
+ documentId,
50
+ requestBody: { requests: [request] },
51
+ });
52
+ return {
53
+ success: true,
54
+ documentId,
55
+ insertedCharacters: text.length,
56
+ mode: index === undefined || index === null ? 'append' : 'insert_at_index',
57
+ };
58
+ } catch (error) {
59
+ throw new Error(docsCommon.formatError(error, 'insert text into'));
60
+ }
61
+ },
62
+ });
@@ -0,0 +1,40 @@
1
+ import { googleDocsAuth, createGoogleClient } from '../auth';
2
+ import { Property, createAction } from '@agnocon/pieces-framework';
3
+ import { docs as googleDocs } from '@googleapis/docs';
4
+ import { readDocumentActionOutputSchema } from '../output-schemas';
5
+
6
+ export const readDocument = createAction({
7
+ displayName: 'Read Document',
8
+ auth: googleDocsAuth,
9
+ name: 'read_document',
10
+ description: 'Read a document from Google Docs',
11
+ audience: 'human',
12
+ aiMetadata: {
13
+ description:
14
+ 'Fetches the full content and structure of a Google Docs document by its ID. Use when an agent needs to inspect, summarize, or extract text from a known document. Requires the document ID (not a name or URL); read-only and idempotent.',
15
+ idempotent: true,
16
+ },
17
+ props: {
18
+ documentId: Property.ShortText({
19
+ displayName: 'Document ID',
20
+ description: 'The ID of the document to read',
21
+ required: true,
22
+ }),
23
+ },
24
+ outputSchema: readDocumentActionOutputSchema,
25
+ async run(context) {
26
+ const authClient = await createGoogleClient(context.auth);
27
+
28
+ const docs = googleDocs({ version: 'v1', auth: authClient });
29
+ const response = await docs.documents.get({
30
+ documentId: context.propsValue.documentId,
31
+ });
32
+
33
+ if (response.status !== 200) {
34
+ console.error(response);
35
+ throw new Error('Error reading document');
36
+ }
37
+
38
+ return response.data;
39
+ },
40
+ });
@@ -0,0 +1,95 @@
1
+ import { googleDocsAuth, createGoogleClient } from '../auth';
2
+ import { Property, createAction } from '@agnocon/pieces-framework';
3
+ import { docs as googleDocs } from '@googleapis/docs';
4
+ import { replaceAllTextActionOutputSchema } from '../output-schemas';
5
+
6
+ export const replaceAllText = createAction({
7
+ auth: googleDocsAuth,
8
+ name: 'replace_all_text',
9
+ displayName: 'Replace All Text in Document',
10
+ description:
11
+ 'Replace every occurrence of a literal string in a Google Docs document with another string.',
12
+ audience: 'ai',
13
+ aiMetadata: {
14
+ // Idempotent matches the sibling create_document_based_on_template, which
15
+ // wraps the identical replaceAllText request and is labeled idempotent:true:
16
+ // re-running with the same find/replace leaves the same end state (the
17
+ // second run matches zero occurrences). Caveat noted below for the
18
+ // overlapping find/replace-literals edge case.
19
+ description:
20
+ 'Find-and-replaces every occurrence of a literal string across a whole Google Docs document. Pick this for a bare ad-hoc text edit; use Edit Template File instead for placeholder-token merges or image swaps. Idempotent for normal use (a repeat run matches nothing and leaves the same end state); the exception is overlapping find/replace literals (e.g. replacing "a" with "ab"), which can re-match on a second run.',
21
+ idempotent: true,
22
+ },
23
+ outputSchema: replaceAllTextActionOutputSchema,
24
+ props: {
25
+ documentId: Property.ShortText({
26
+ displayName: 'Document ID',
27
+ description:
28
+ "The ID of the document to edit, found in its URL: 'https://docs.google.com/document/d/<documentId>/edit'.",
29
+ required: true,
30
+ }),
31
+ find_text: Property.ShortText({
32
+ displayName: 'Find Text',
33
+ description: 'The literal text to search for in the document.',
34
+ required: true,
35
+ }),
36
+ replace_text: Property.ShortText({
37
+ displayName: 'Replace With',
38
+ description: 'The text to replace every matched occurrence with.',
39
+ required: true,
40
+ }),
41
+ match_case: Property.Checkbox({
42
+ displayName: 'Match Case',
43
+ description: 'When enabled, the search is case-sensitive.',
44
+ required: false,
45
+ defaultValue: false,
46
+ }),
47
+ },
48
+ async run(context) {
49
+ const { documentId, find_text, replace_text, match_case } =
50
+ context.propsValue;
51
+
52
+ const authClient = await createGoogleClient(context.auth);
53
+ const docs = googleDocs({ version: 'v1', auth: authClient });
54
+
55
+ try {
56
+ const response = await docs.documents.batchUpdate({
57
+ documentId,
58
+ requestBody: {
59
+ requests: [
60
+ {
61
+ replaceAllText: {
62
+ containsText: {
63
+ text: find_text,
64
+ matchCase: match_case ?? false,
65
+ },
66
+ replaceText: replace_text,
67
+ },
68
+ },
69
+ ],
70
+ },
71
+ });
72
+
73
+ const occurrencesChanged =
74
+ response.data.replies?.[0]?.replaceAllText?.occurrencesChanged ?? 0;
75
+
76
+ return {
77
+ documentId,
78
+ occurrencesChanged,
79
+ };
80
+ } catch (e) {
81
+ const error = e as { code?: number; message?: string };
82
+ if (error.code === 403) {
83
+ throw new Error(
84
+ 'Permission denied editing the document. Ensure the connected account has edit access to this document.'
85
+ );
86
+ }
87
+ if (error.code === 404) {
88
+ throw new Error(
89
+ `Document not found for ID '${documentId}'. Verify the document ID.`
90
+ );
91
+ }
92
+ throw e;
93
+ }
94
+ },
95
+ });
@@ -0,0 +1,76 @@
1
+ import { googleDocsAuth, createGoogleClient } from '../auth';
2
+ import { docsCommon } from '../common';
3
+ import { Property, createAction } from '@agnocon/pieces-framework';
4
+ import { docs as googleDocs, docs_v1 } from '@googleapis/docs';
5
+ import { replaceBodyWithMarkdownActionOutputSchema } from '../output-schemas';
6
+
7
+ export const replaceBodyWithMarkdown = createAction({
8
+ auth: googleDocsAuth,
9
+ name: 'replace_body_with_markdown',
10
+ displayName: 'Replace Body with Markdown',
11
+ description: 'Replace the entire body of a Google Docs document with Markdown content',
12
+ audience: 'ai',
13
+ aiMetadata: {
14
+ description:
15
+ 'Clears the entire body of an existing Google Docs document and repopulates it from Markdown text, converting headings (#, ##, ###), bullet lists (-, *, +), and paragraphs into native Google Docs formatting. Use when an agent wants to overwrite a document wholesale with freshly generated Markdown (the format LLMs produce natively) in one call. Inline styling such as bold/italic is inserted as plain text. Not supported when the body contains a table or table of contents — the action errors clearly instead of partially failing. Destructive and not idempotent: the previous body content is deleted.',
16
+ idempotent: false,
17
+ },
18
+ outputSchema: replaceBodyWithMarkdownActionOutputSchema,
19
+ props: {
20
+ documentId: Property.ShortText({
21
+ displayName: 'Document ID',
22
+ description: 'The ID of the document to overwrite.',
23
+ required: true,
24
+ }),
25
+ markdown: Property.LongText({
26
+ displayName: 'Markdown Content',
27
+ description: 'Markdown text. Supports headings (#/##/###), bullet lists (-/*/+), and paragraphs.',
28
+ required: true,
29
+ }),
30
+ },
31
+ async run(context) {
32
+ const { documentId, markdown } = context.propsValue;
33
+ const authClient = await createGoogleClient(context.auth);
34
+ const docs = googleDocs({ version: 'v1', auth: authClient });
35
+
36
+ let bodyEnd: number;
37
+ let hasStructuralElement = false;
38
+ try {
39
+ const response = await docs.documents.get({ documentId });
40
+ const content = response.data.body?.content ?? [];
41
+ const lastElement = content[content.length - 1];
42
+ bodyEnd = lastElement?.endIndex ?? 1;
43
+ // A single deleteContentRange cannot remove a table or table of contents
44
+ // that the range crosses, so a wholesale body replace is unsupported then.
45
+ hasStructuralElement = content.some((element) => element.table || element.tableOfContents);
46
+ } catch (error) {
47
+ throw new Error(docsCommon.formatError(error, 'read'));
48
+ }
49
+
50
+ if (hasStructuralElement) {
51
+ throw new Error(
52
+ 'Cannot replace the body wholesale because it contains a table or table of contents, which deleteContentRange cannot remove. Remove those elements first, or edit the document with the targeted table/section atomics.'
53
+ );
54
+ }
55
+
56
+ const requests: docs_v1.Schema$Request[] = [];
57
+ // The body always ends in an undeletable trailing newline, so the deletable
58
+ // range is [1, bodyEnd-1); only delete when there is real content to remove.
59
+ if (bodyEnd > 2) {
60
+ requests.push({ deleteContentRange: { range: { startIndex: 1, endIndex: bodyEnd - 1 } } });
61
+ }
62
+ requests.push(...docsCommon.markdownToBatchRequests(markdown));
63
+
64
+ try {
65
+ await docs.documents.batchUpdate({ documentId, requestBody: { requests } });
66
+ } catch (error) {
67
+ throw new Error(docsCommon.formatError(error, 'replace the body of'));
68
+ }
69
+
70
+ return {
71
+ success: true,
72
+ documentId,
73
+ url: `https://docs.google.com/document/d/${documentId}/edit`,
74
+ };
75
+ },
76
+ });
@@ -0,0 +1,60 @@
1
+ import { googleDocsAuth, createGoogleClient } from '../auth';
2
+ import { docsCommon } from '../common';
3
+ import { Property, createAction } from '@agnocon/pieces-framework';
4
+ import { docs as googleDocs, docs_v1 } from '@googleapis/docs';
5
+ import { replaceImageActionOutputSchema } from '../output-schemas';
6
+
7
+ export const replaceImage = createAction({
8
+ auth: googleDocsAuth,
9
+ name: 'replace_image',
10
+ displayName: 'Replace Image',
11
+ description: 'Replace an existing inline image in a Google Docs document with a new image from a URI.',
12
+ audience: 'ai',
13
+ aiMetadata: {
14
+ description:
15
+ 'Swaps an existing inline image (identified by its object ID) for a new image at the given URI. Use this to update a specific image in a document without altering surrounding content. The imageObjectId must come from the document\'s inlineObjects map — obtain it by calling Read Document first. Re-running with the same URI leaves the document in the same visual state, so it is idempotent.',
16
+ idempotent: true,
17
+ },
18
+ outputSchema: replaceImageActionOutputSchema,
19
+ props: {
20
+ documentId: Property.ShortText({
21
+ displayName: 'Document ID',
22
+ description: 'The ID of the document containing the image to replace.',
23
+ required: true,
24
+ }),
25
+ imageObjectId: Property.ShortText({
26
+ displayName: 'Image Object ID',
27
+ description:
28
+ 'The object ID of the inline image to replace. This is a hidden ID found in the document\'s inlineObjects map — obtain it by calling Read Document and inspecting the inlineObjects field.',
29
+ required: true,
30
+ }),
31
+ uri: Property.ShortText({
32
+ displayName: 'New Image URI',
33
+ description: 'A publicly accessible URL of the replacement image. Google must be able to fetch this URL at the time of the call.',
34
+ required: true,
35
+ }),
36
+ },
37
+ async run(context) {
38
+ const { documentId, imageObjectId, uri } = context.propsValue;
39
+ const authClient = await createGoogleClient(context.auth);
40
+ const docs = googleDocs({ version: 'v1', auth: authClient });
41
+
42
+ const request: docs_v1.Schema$Request = {
43
+ replaceImage: {
44
+ imageObjectId,
45
+ uri,
46
+ imageReplaceMethod: 'CENTER_CROP',
47
+ },
48
+ };
49
+
50
+ try {
51
+ await docs.documents.batchUpdate({
52
+ documentId,
53
+ requestBody: { requests: [request] },
54
+ });
55
+ return { success: true, documentId, imageObjectId };
56
+ } catch (error) {
57
+ throw new Error(docsCommon.formatError(error, 'replace image in'));
58
+ }
59
+ },
60
+ });
@@ -0,0 +1,104 @@
1
+ import { googleDocsAuth, createGoogleClient } from '../auth';
2
+ import { docsCommon } from '../common';
3
+ import { Property, createAction } from '@agnocon/pieces-framework';
4
+ import { docs as googleDocs, docs_v1 } from '@googleapis/docs';
5
+ import { replaceSectionWithMarkdownActionOutputSchema } from '../output-schemas';
6
+
7
+ export const replaceSectionWithMarkdown = createAction({
8
+ auth: googleDocsAuth,
9
+ name: 'replace_section_with_markdown',
10
+ displayName: 'Replace Section with Markdown',
11
+ description: 'Replace a character range of a Google Docs document with Markdown content',
12
+ audience: 'ai',
13
+ aiMetadata: {
14
+ description:
15
+ 'Deletes the content between a start and end character index and replaces it with text rendered from Markdown (headings #/##/###, bullet lists -/*/+, paragraphs converted to native Google Docs formatting). Use when an agent wants to overwrite one section of a document — not the whole body — with freshly generated Markdown. Obtain start and end indices from Read Document first; indices cannot be guessed. If the end index reaches the document end it is clamped to exclude the undeletable terminal newline. Inline styling such as bold/italic is inserted as plain text. Destructive and not idempotent.',
16
+ idempotent: false,
17
+ },
18
+ outputSchema: replaceSectionWithMarkdownActionOutputSchema,
19
+ props: {
20
+ documentId: Property.ShortText({
21
+ displayName: 'Document ID',
22
+ description: 'The ID of the document to edit.',
23
+ required: true,
24
+ }),
25
+ startIndex: Property.Number({
26
+ displayName: 'Start Index',
27
+ description: 'Inclusive start character index of the section to replace. Obtain from Read Document.',
28
+ required: true,
29
+ }),
30
+ endIndex: Property.Number({
31
+ displayName: 'End Index',
32
+ description:
33
+ 'Exclusive end character index of the section to replace. Must be greater than Start Index and obtained from Read Document.',
34
+ required: true,
35
+ }),
36
+ markdown: Property.LongText({
37
+ displayName: 'Markdown Content',
38
+ description: 'Markdown text. Supports headings (#/##/###), bullet lists (-/*/+), and paragraphs.',
39
+ required: true,
40
+ }),
41
+ },
42
+ async run(context) {
43
+ const { documentId, startIndex, markdown } = context.propsValue;
44
+ let { endIndex } = context.propsValue;
45
+ if (endIndex <= startIndex) {
46
+ throw new Error('End Index must be greater than Start Index.');
47
+ }
48
+
49
+ const authClient = await createGoogleClient(context.auth);
50
+ const docs = googleDocs({ version: 'v1', auth: authClient });
51
+
52
+ // The body's terminal newline cannot be deleted, so if the caller passed an
53
+ // end index at/after the body end (e.g. the value from Get Document End Index)
54
+ // clamp it to one before the end — otherwise deleteContentRange 400s.
55
+ let content: docs_v1.Schema$StructuralElement[];
56
+ try {
57
+ const response = await docs.documents.get({ documentId });
58
+ content = response.data.body?.content ?? [];
59
+ } catch (error) {
60
+ throw new Error(docsCommon.formatError(error, 'read'));
61
+ }
62
+ const bodyEnd = content[content.length - 1]?.endIndex ?? endIndex;
63
+ if (endIndex > bodyEnd - 1) {
64
+ endIndex = bodyEnd - 1;
65
+ }
66
+ if (endIndex <= startIndex) {
67
+ throw new Error('The section to replace is empty after clamping the end index to the document end.');
68
+ }
69
+ // A single deleteContentRange cannot remove a table or table of contents
70
+ // that the range crosses, so a section replace over one is unsupported.
71
+ const crossesStructuralElement = content.some(
72
+ (element) =>
73
+ (element.table || element.tableOfContents) &&
74
+ (element.startIndex ?? 0) < endIndex &&
75
+ (element.endIndex ?? 0) > startIndex
76
+ );
77
+ if (crossesStructuralElement) {
78
+ throw new Error(
79
+ 'Cannot replace this section because it contains or overlaps a table or table of contents, which deleteContentRange cannot remove. Choose a range that excludes it, or edit it with the targeted table atomics.'
80
+ );
81
+ }
82
+
83
+ // Delete the section first, then insert the markdown at the now-empty
84
+ // startIndex; the converter builds its inserts from that base index.
85
+ const requests: docs_v1.Schema$Request[] = [
86
+ { deleteContentRange: { range: { startIndex, endIndex } } },
87
+ ...docsCommon.markdownToBatchRequests(markdown, startIndex),
88
+ ];
89
+
90
+ try {
91
+ await docs.documents.batchUpdate({ documentId, requestBody: { requests } });
92
+ } catch (error) {
93
+ throw new Error(docsCommon.formatError(error, 'replace a section of'));
94
+ }
95
+
96
+ return {
97
+ success: true,
98
+ documentId,
99
+ replacedFrom: startIndex,
100
+ replacedTo: endIndex,
101
+ url: `https://docs.google.com/document/d/${documentId}/edit`,
102
+ };
103
+ },
104
+ });
@@ -0,0 +1,131 @@
1
+ import { googleDocsAuth, createGoogleClient } from '../auth';
2
+ import { Property, createAction } from '@agnocon/pieces-framework';
3
+ import { drive as googleDrive } from '@googleapis/drive';
4
+ import { searchDocumentsActionOutputSchema } from '../output-schemas';
5
+
6
+ export const searchDocuments = createAction({
7
+ auth: googleDocsAuth,
8
+ name: 'search_documents',
9
+ displayName: 'Search Documents',
10
+ description:
11
+ 'Search Google Drive for Google Docs documents by name or full-text content.',
12
+ audience: 'ai',
13
+ aiMetadata: {
14
+ description:
15
+ "Searches Drive for Google Docs documents by name and/or full-text content, returning multiple ordered results with their IDs. Pick this over Find Document to discover documents by their content (not just an exact name) or to get more than one match; Find Document returns only the first name match and can also create-if-missing. Read-only and idempotent. At least one of name/content text is required.",
16
+ idempotent: true,
17
+ },
18
+ outputSchema: searchDocumentsActionOutputSchema,
19
+ props: {
20
+ name_contains: Property.ShortText({
21
+ displayName: 'Name Contains',
22
+ description:
23
+ 'Return documents whose name contains this text. Provide this and/or Content Contains.',
24
+ required: false,
25
+ }),
26
+ full_text_contains: Property.ShortText({
27
+ displayName: 'Content Contains',
28
+ description:
29
+ 'Return documents whose full text content contains this text. Provide this and/or Name Contains.',
30
+ required: false,
31
+ }),
32
+ max_results: Property.Number({
33
+ displayName: 'Max Results',
34
+ description: 'Maximum number of documents to return (1-100).',
35
+ required: false,
36
+ defaultValue: 10,
37
+ }),
38
+ order_by: Property.StaticDropdown({
39
+ displayName: 'Order By',
40
+ description: 'How to sort the results.',
41
+ required: false,
42
+ defaultValue: 'modifiedTime desc',
43
+ options: {
44
+ options: [
45
+ { label: 'Last modified (newest first)', value: 'modifiedTime desc' },
46
+ { label: 'Last modified (oldest first)', value: 'modifiedTime' },
47
+ { label: 'Created (newest first)', value: 'createdTime desc' },
48
+ { label: 'Created (oldest first)', value: 'createdTime' },
49
+ { label: 'Name (A-Z)', value: 'name' },
50
+ { label: 'Name (Z-A)', value: 'name desc' },
51
+ ],
52
+ },
53
+ }),
54
+ page_token: Property.ShortText({
55
+ displayName: 'Page Token',
56
+ description:
57
+ 'Token for the next page of results, taken from the nextPageToken of a previous call. Leave empty for the first page.',
58
+ required: false,
59
+ }),
60
+ },
61
+ async run(context) {
62
+ const { name_contains, full_text_contains, max_results, order_by, page_token } =
63
+ context.propsValue;
64
+
65
+ if (!name_contains && !full_text_contains) {
66
+ throw new Error(
67
+ 'Provide at least one of "Name Contains" or "Content Contains" to search.'
68
+ );
69
+ }
70
+
71
+ const pageSize = Math.min(Math.max(max_results ?? 10, 1), 100);
72
+
73
+ const matchClauses: string[] = [];
74
+ if (name_contains) {
75
+ matchClauses.push(
76
+ `name contains '${name_contains.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`
77
+ );
78
+ }
79
+ if (full_text_contains) {
80
+ matchClauses.push(
81
+ `fullText contains '${full_text_contains.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`
82
+ );
83
+ }
84
+
85
+ const query = [
86
+ `mimeType='application/vnd.google-apps.document'`,
87
+ `(${matchClauses.join(' or ')})`,
88
+ 'trashed=false',
89
+ ].join(' and ');
90
+
91
+ const authClient = await createGoogleClient(context.auth);
92
+ const drive = googleDrive({ version: 'v3', auth: authClient });
93
+
94
+ try {
95
+ const response = await drive.files.list({
96
+ q: query,
97
+ orderBy: order_by ?? 'modifiedTime desc',
98
+ pageSize,
99
+ pageToken: page_token || undefined,
100
+ supportsAllDrives: true,
101
+ includeItemsFromAllDrives: true,
102
+ corpora: 'allDrives',
103
+ fields:
104
+ 'nextPageToken, files(id, name, mimeType, createdTime, modifiedTime, webViewLink, owners(emailAddress))',
105
+ });
106
+
107
+ const documents = (response.data.files ?? []).map((file) => ({
108
+ id: file.id ?? '',
109
+ name: file.name ?? '',
110
+ createdTime: file.createdTime ?? '',
111
+ modifiedTime: file.modifiedTime ?? '',
112
+ webViewLink: file.webViewLink ?? '',
113
+ ownerEmail: file.owners?.[0]?.emailAddress ?? '',
114
+ }));
115
+
116
+ return {
117
+ documents,
118
+ count: documents.length,
119
+ nextPageToken: response.data.nextPageToken ?? null,
120
+ };
121
+ } catch (e) {
122
+ const error = e as { code?: number; message?: string };
123
+ if (error.code === 403) {
124
+ throw new Error(
125
+ 'Permission denied searching Drive. Ensure the connected account has Drive access.'
126
+ );
127
+ }
128
+ throw e;
129
+ }
130
+ },
131
+ });
@@ -0,0 +1,88 @@
1
+ import { googleDocsAuth, createGoogleClient } from '../auth';
2
+ import { docsCommon } from '../common';
3
+ import { Property, createAction } from '@agnocon/pieces-framework';
4
+ import { docs as googleDocs, docs_v1 } from '@googleapis/docs';
5
+ import { unmergeTableCellsActionOutputSchema } from '../output-schemas';
6
+
7
+ export const unmergeTableCells = createAction({
8
+ auth: googleDocsAuth,
9
+ name: 'unmerge_table_cells',
10
+ displayName: 'Unmerge Table Cells',
11
+ description: 'Unmerge previously merged table cells in a Google Docs document',
12
+ audience: 'ai',
13
+ aiMetadata: {
14
+ description:
15
+ 'Unmerges a range of previously merged table cells in a Google Docs document. The range is specified by the anchor cell (rowIndex, columnIndex) and the span (rowSpan, columnSpan) to unmerge. Requires the table start index from Read Document — cannot be guessed. Idempotent: unmerging already-unmerged cells is a no-op.',
16
+ idempotent: true,
17
+ },
18
+ outputSchema: unmergeTableCellsActionOutputSchema,
19
+ props: {
20
+ documentId: Property.ShortText({
21
+ displayName: 'Document ID',
22
+ description: 'The ID of the document containing the table.',
23
+ required: true,
24
+ }),
25
+ tableStartIndex: Property.Number({
26
+ displayName: 'Table Start Index',
27
+ description: 'Obtain the table start index from Read Document — cannot be guessed.',
28
+ required: true,
29
+ }),
30
+ rowIndex: Property.Number({
31
+ displayName: 'Row Index',
32
+ description: 'Zero-based row index of the top-left anchor cell of the merged region.',
33
+ required: true,
34
+ }),
35
+ columnIndex: Property.Number({
36
+ displayName: 'Column Index',
37
+ description: 'Zero-based column index of the top-left anchor cell of the merged region.',
38
+ required: true,
39
+ }),
40
+ rowSpan: Property.Number({
41
+ displayName: 'Row Span',
42
+ description: 'Number of rows covered by the merged region to unmerge.',
43
+ required: true,
44
+ }),
45
+ columnSpan: Property.Number({
46
+ displayName: 'Column Span',
47
+ description: 'Number of columns covered by the merged region to unmerge.',
48
+ required: true,
49
+ }),
50
+ },
51
+ async run(context) {
52
+ const { documentId, tableStartIndex, rowIndex, columnIndex, rowSpan, columnSpan } = context.propsValue;
53
+ const authClient = await createGoogleClient(context.auth);
54
+ const docs = googleDocs({ version: 'v1', auth: authClient });
55
+
56
+ const request: docs_v1.Schema$Request = {
57
+ unmergeTableCells: {
58
+ tableRange: {
59
+ tableCellLocation: {
60
+ tableStartLocation: { index: tableStartIndex },
61
+ rowIndex,
62
+ columnIndex,
63
+ },
64
+ rowSpan,
65
+ columnSpan,
66
+ },
67
+ },
68
+ };
69
+
70
+ try {
71
+ await docs.documents.batchUpdate({
72
+ documentId,
73
+ requestBody: { requests: [request] },
74
+ });
75
+ return {
76
+ success: true,
77
+ documentId,
78
+ tableStartIndex,
79
+ rowIndex,
80
+ columnIndex,
81
+ rowSpan,
82
+ columnSpan,
83
+ };
84
+ } catch (error) {
85
+ throw new Error(docsCommon.formatError(error, 'unmerge table cells in'));
86
+ }
87
+ },
88
+ });