@commandable/integration-data 0.0.1

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 (335) hide show
  1. package/dist/credentials-index.d.ts +30 -0
  2. package/dist/credentials-index.d.ts.map +1 -0
  3. package/dist/credentials-index.js +292 -0
  4. package/dist/credentials-index.js.map +1 -0
  5. package/dist/index.d.ts +3 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +2 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/loader.d.ts +69 -0
  10. package/dist/loader.d.ts.map +1 -0
  11. package/dist/loader.js +164 -0
  12. package/dist/loader.js.map +1 -0
  13. package/integrations/README.md +52 -0
  14. package/integrations/airtable/__tests__/get_handlers.test.ts +137 -0
  15. package/integrations/airtable/__tests__/usage_parity.test.ts +35 -0
  16. package/integrations/airtable/__tests__/write_and_admin_handlers.test.ts +113 -0
  17. package/integrations/airtable/credentials.json +20 -0
  18. package/integrations/airtable/credentials_hint.md +4 -0
  19. package/integrations/airtable/handlers/create_record.js +12 -0
  20. package/integrations/airtable/handlers/delete_record.js +7 -0
  21. package/integrations/airtable/handlers/get_record.js +4 -0
  22. package/integrations/airtable/handlers/get_table_schema.js +6 -0
  23. package/integrations/airtable/handlers/list_bases.js +4 -0
  24. package/integrations/airtable/handlers/list_records.js +25 -0
  25. package/integrations/airtable/handlers/list_table_fields.js +6 -0
  26. package/integrations/airtable/handlers/list_tables.js +4 -0
  27. package/integrations/airtable/handlers/list_views.js +6 -0
  28. package/integrations/airtable/handlers/search_records.js +6 -0
  29. package/integrations/airtable/handlers/update_record.js +11 -0
  30. package/integrations/airtable/manifest.json +83 -0
  31. package/integrations/airtable/schemas/create_record.json +12 -0
  32. package/integrations/airtable/schemas/delete_record.json +11 -0
  33. package/integrations/airtable/schemas/empty.json +6 -0
  34. package/integrations/airtable/schemas/get_record.json +11 -0
  35. package/integrations/airtable/schemas/id_base.json +9 -0
  36. package/integrations/airtable/schemas/id_base_table.json +10 -0
  37. package/integrations/airtable/schemas/list_records.json +26 -0
  38. package/integrations/airtable/schemas/search_records.json +12 -0
  39. package/integrations/airtable/schemas/update_record.json +13 -0
  40. package/integrations/github/__tests__/get_handlers.test.ts +117 -0
  41. package/integrations/github/__tests__/usage_parity.test.ts +34 -0
  42. package/integrations/github/__tests__/write_handlers.test.ts +311 -0
  43. package/integrations/github/credentials.json +20 -0
  44. package/integrations/github/credentials_hint.md +7 -0
  45. package/integrations/github/handlers/add_labels_to_issue.js +12 -0
  46. package/integrations/github/handlers/close_issue.js +5 -0
  47. package/integrations/github/handlers/comment_on_issue.js +5 -0
  48. package/integrations/github/handlers/create_branch.js +33 -0
  49. package/integrations/github/handlers/create_commit.js +91 -0
  50. package/integrations/github/handlers/create_issue.js +10 -0
  51. package/integrations/github/handlers/create_or_update_file.js +21 -0
  52. package/integrations/github/handlers/create_pull_request.js +16 -0
  53. package/integrations/github/handlers/create_repo.js +11 -0
  54. package/integrations/github/handlers/delete_repo.js +6 -0
  55. package/integrations/github/handlers/get_issue.js +4 -0
  56. package/integrations/github/handlers/get_repo.js +4 -0
  57. package/integrations/github/handlers/list_branches.js +4 -0
  58. package/integrations/github/handlers/list_commits.js +12 -0
  59. package/integrations/github/handlers/list_issues.js +12 -0
  60. package/integrations/github/handlers/list_pull_requests.js +8 -0
  61. package/integrations/github/handlers/list_repos_install.js +4 -0
  62. package/integrations/github/handlers/list_repos_user.js +4 -0
  63. package/integrations/github/handlers/merge_pull_request.js +14 -0
  64. package/integrations/github/handlers/update_issue.js +15 -0
  65. package/integrations/github/manifest.json +26 -0
  66. package/integrations/github/schemas/add_labels_to_issue.json +12 -0
  67. package/integrations/github/schemas/close_issue.json +10 -0
  68. package/integrations/github/schemas/comment_on_issue.json +11 -0
  69. package/integrations/github/schemas/create_branch.json +12 -0
  70. package/integrations/github/schemas/create_commit.json +25 -0
  71. package/integrations/github/schemas/create_issue.json +13 -0
  72. package/integrations/github/schemas/create_or_update_file.json +15 -0
  73. package/integrations/github/schemas/create_pull_request.json +15 -0
  74. package/integrations/github/schemas/create_repo.json +12 -0
  75. package/integrations/github/schemas/delete_repo.json +10 -0
  76. package/integrations/github/schemas/empty.json +5 -0
  77. package/integrations/github/schemas/get_issue.json +10 -0
  78. package/integrations/github/schemas/get_repo.json +9 -0
  79. package/integrations/github/schemas/list_commits.json +12 -0
  80. package/integrations/github/schemas/list_issues.json +12 -0
  81. package/integrations/github/schemas/list_pull_requests.json +10 -0
  82. package/integrations/github/schemas/merge_pull_request.json +14 -0
  83. package/integrations/github/schemas/owner_repo.json +9 -0
  84. package/integrations/github/schemas/update_issue.json +15 -0
  85. package/integrations/google-calendar/__tests__/get_handlers.test.ts +112 -0
  86. package/integrations/google-calendar/__tests__/usage_parity.test.ts +34 -0
  87. package/integrations/google-calendar/__tests__/write_and_admin_handlers.test.ts +161 -0
  88. package/integrations/google-calendar/credentials.json +36 -0
  89. package/integrations/google-calendar/credentials_hint.md +9 -0
  90. package/integrations/google-calendar/handlers/create_event.js +6 -0
  91. package/integrations/google-calendar/handlers/delete_acl.js +6 -0
  92. package/integrations/google-calendar/handlers/delete_event.js +7 -0
  93. package/integrations/google-calendar/handlers/freebusy_query.js +4 -0
  94. package/integrations/google-calendar/handlers/get_acl.js +5 -0
  95. package/integrations/google-calendar/handlers/get_calendar.js +4 -0
  96. package/integrations/google-calendar/handlers/get_event.js +5 -0
  97. package/integrations/google-calendar/handlers/insert_acl.js +6 -0
  98. package/integrations/google-calendar/handlers/list_acl.js +5 -0
  99. package/integrations/google-calendar/handlers/list_calendars.js +4 -0
  100. package/integrations/google-calendar/handlers/list_colors.js +4 -0
  101. package/integrations/google-calendar/handlers/list_events.js +21 -0
  102. package/integrations/google-calendar/handlers/list_settings.js +4 -0
  103. package/integrations/google-calendar/handlers/move_event.js +6 -0
  104. package/integrations/google-calendar/handlers/patch_event.js +5 -0
  105. package/integrations/google-calendar/handlers/quick_add.js +6 -0
  106. package/integrations/google-calendar/handlers/update_acl.js +7 -0
  107. package/integrations/google-calendar/handlers/update_event.js +5 -0
  108. package/integrations/google-calendar/manifest.json +26 -0
  109. package/integrations/google-calendar/schemas/create_event.json +34 -0
  110. package/integrations/google-calendar/schemas/delete_acl.json +9 -0
  111. package/integrations/google-calendar/schemas/empty.json +1 -0
  112. package/integrations/google-calendar/schemas/freebusy_query.json +13 -0
  113. package/integrations/google-calendar/schemas/get_acl.json +9 -0
  114. package/integrations/google-calendar/schemas/id_calendar.json +8 -0
  115. package/integrations/google-calendar/schemas/id_calendar_event.json +9 -0
  116. package/integrations/google-calendar/schemas/insert_acl.json +18 -0
  117. package/integrations/google-calendar/schemas/list_events.json +15 -0
  118. package/integrations/google-calendar/schemas/move_event.json +10 -0
  119. package/integrations/google-calendar/schemas/patch_event.json +10 -0
  120. package/integrations/google-calendar/schemas/quick_add.json +9 -0
  121. package/integrations/google-calendar/schemas/update_acl.json +10 -0
  122. package/integrations/google-calendar/schemas/update_event.json +10 -0
  123. package/integrations/google-docs/__tests__/get_handlers.test.ts +72 -0
  124. package/integrations/google-docs/__tests__/usage_parity.test.ts +34 -0
  125. package/integrations/google-docs/__tests__/write_handlers.test.ts +249 -0
  126. package/integrations/google-docs/credentials.json +36 -0
  127. package/integrations/google-docs/credentials_hint.md +9 -0
  128. package/integrations/google-docs/handlers/append_text.js +12 -0
  129. package/integrations/google-docs/handlers/batch_update.js +13 -0
  130. package/integrations/google-docs/handlers/create_document.js +9 -0
  131. package/integrations/google-docs/handlers/delete_first_match.js +50 -0
  132. package/integrations/google-docs/handlers/get_document.js +12 -0
  133. package/integrations/google-docs/handlers/get_document_structured.js +6 -0
  134. package/integrations/google-docs/handlers/get_document_text.js +17 -0
  135. package/integrations/google-docs/handlers/insert_inline_image_after_first_match.js +41 -0
  136. package/integrations/google-docs/handlers/insert_page_break_after_first_match.js +49 -0
  137. package/integrations/google-docs/handlers/insert_table_after_first_match.js +49 -0
  138. package/integrations/google-docs/handlers/insert_text_after_first_match.js +51 -0
  139. package/integrations/google-docs/handlers/replace_all_text.js +8 -0
  140. package/integrations/google-docs/handlers/style_first_match.js +42 -0
  141. package/integrations/google-docs/handlers/update_document_style.js +8 -0
  142. package/integrations/google-docs/handlers/update_paragraph_style_for_first_match.js +48 -0
  143. package/integrations/google-docs/manifest.json +58 -0
  144. package/integrations/google-docs/schemas/append_text.json +10 -0
  145. package/integrations/google-docs/schemas/apply_text_style.json +13 -0
  146. package/integrations/google-docs/schemas/batch_update.json +16 -0
  147. package/integrations/google-docs/schemas/create_document.json +8 -0
  148. package/integrations/google-docs/schemas/delete_content_range.json +11 -0
  149. package/integrations/google-docs/schemas/delete_first_match.json +10 -0
  150. package/integrations/google-docs/schemas/get_document.json +11 -0
  151. package/integrations/google-docs/schemas/get_document_structured.json +9 -0
  152. package/integrations/google-docs/schemas/get_document_text.json +9 -0
  153. package/integrations/google-docs/schemas/insert_inline_image.json +12 -0
  154. package/integrations/google-docs/schemas/insert_inline_image_after_first_match.json +13 -0
  155. package/integrations/google-docs/schemas/insert_page_break.json +10 -0
  156. package/integrations/google-docs/schemas/insert_page_break_after_first_match.json +11 -0
  157. package/integrations/google-docs/schemas/insert_table.json +12 -0
  158. package/integrations/google-docs/schemas/insert_table_after_first_match.json +13 -0
  159. package/integrations/google-docs/schemas/insert_text_after_first_match.json +12 -0
  160. package/integrations/google-docs/schemas/insert_text_at.json +11 -0
  161. package/integrations/google-docs/schemas/replace_all_text.json +12 -0
  162. package/integrations/google-docs/schemas/style_first_match.json +12 -0
  163. package/integrations/google-docs/schemas/update_document_style.json +11 -0
  164. package/integrations/google-docs/schemas/update_paragraph_style.json +13 -0
  165. package/integrations/google-docs/schemas/update_paragraph_style_for_first_match.json +12 -0
  166. package/integrations/google-sheet/__tests__/get_handlers.test.ts +129 -0
  167. package/integrations/google-sheet/__tests__/usage_parity.test.ts +35 -0
  168. package/integrations/google-sheet/__tests__/write_handlers.test.ts +171 -0
  169. package/integrations/google-sheet/credentials.json +36 -0
  170. package/integrations/google-sheet/credentials_hint.md +9 -0
  171. package/integrations/google-sheet/handlers/append_values.js +18 -0
  172. package/integrations/google-sheet/handlers/batch_clear_values.js +6 -0
  173. package/integrations/google-sheet/handlers/batch_clear_values_by_data_filter.js +6 -0
  174. package/integrations/google-sheet/handlers/batch_get_values.js +16 -0
  175. package/integrations/google-sheet/handlers/batch_update.js +14 -0
  176. package/integrations/google-sheet/handlers/batch_update_values.js +16 -0
  177. package/integrations/google-sheet/handlers/batch_update_values_by_data_filter.js +16 -0
  178. package/integrations/google-sheet/handlers/clear_values.js +6 -0
  179. package/integrations/google-sheet/handlers/copy_to_spreadsheet.js +6 -0
  180. package/integrations/google-sheet/handlers/create_spreadsheet.js +5 -0
  181. package/integrations/google-sheet/handlers/get_developer_metadata.js +6 -0
  182. package/integrations/google-sheet/handlers/get_spreadsheet.js +12 -0
  183. package/integrations/google-sheet/handlers/get_spreadsheet_by_data_filter.js +10 -0
  184. package/integrations/google-sheet/handlers/get_values.js +14 -0
  185. package/integrations/google-sheet/handlers/get_values_by_data_filter.js +14 -0
  186. package/integrations/google-sheet/handlers/search_developer_metadata.js +7 -0
  187. package/integrations/google-sheet/handlers/update_values.js +16 -0
  188. package/integrations/google-sheet/manifest.json +125 -0
  189. package/integrations/google-sheet/schemas/append_values.json +16 -0
  190. package/integrations/google-sheet/schemas/batch_clear_values.json +10 -0
  191. package/integrations/google-sheet/schemas/batch_clear_values_by_data_filter.json +10 -0
  192. package/integrations/google-sheet/schemas/batch_get_values.json +13 -0
  193. package/integrations/google-sheet/schemas/batch_update.json +13 -0
  194. package/integrations/google-sheet/schemas/batch_update_values.json +25 -0
  195. package/integrations/google-sheet/schemas/batch_update_values_by_data_filter.json +25 -0
  196. package/integrations/google-sheet/schemas/clear_values.json +10 -0
  197. package/integrations/google-sheet/schemas/copy_to_spreadsheet.json +11 -0
  198. package/integrations/google-sheet/schemas/create_spreadsheet.json +11 -0
  199. package/integrations/google-sheet/schemas/get_developer_metadata.json +10 -0
  200. package/integrations/google-sheet/schemas/get_spreadsheet.json +15 -0
  201. package/integrations/google-sheet/schemas/get_spreadsheet_by_data_filter.json +11 -0
  202. package/integrations/google-sheet/schemas/get_values.json +13 -0
  203. package/integrations/google-sheet/schemas/get_values_by_data_filter.json +17 -0
  204. package/integrations/google-sheet/schemas/search_developer_metadata.json +14 -0
  205. package/integrations/google-sheet/schemas/update_values.json +15 -0
  206. package/integrations/google-slides/__tests__/get_handlers.test.ts +69 -0
  207. package/integrations/google-slides/__tests__/usage_parity.test.ts +34 -0
  208. package/integrations/google-slides/__tests__/write_handlers.test.ts +125 -0
  209. package/integrations/google-slides/credentials.json +36 -0
  210. package/integrations/google-slides/credentials_hint.md +9 -0
  211. package/integrations/google-slides/handlers/append_text_to_title_of_first_slide.js +17 -0
  212. package/integrations/google-slides/handlers/batch_update.js +15 -0
  213. package/integrations/google-slides/handlers/create_presentation.js +8 -0
  214. package/integrations/google-slides/handlers/create_slide_after_first_match.js +20 -0
  215. package/integrations/google-slides/handlers/get_page_thumbnail.js +12 -0
  216. package/integrations/google-slides/handlers/get_presentation.js +6 -0
  217. package/integrations/google-slides/handlers/insert_image_after_first_match.js +19 -0
  218. package/integrations/google-slides/handlers/insert_shape_after_first_match.js +21 -0
  219. package/integrations/google-slides/handlers/replace_text_first_match.js +9 -0
  220. package/integrations/google-slides/handlers/set_background_color_for_slide_index.js +15 -0
  221. package/integrations/google-slides/handlers/style_text_first_match.js +48 -0
  222. package/integrations/google-slides/manifest.json +41 -0
  223. package/integrations/google-slides/schemas/append_text_to_title_of_first_slide.json +11 -0
  224. package/integrations/google-slides/schemas/batch_update.json +13 -0
  225. package/integrations/google-slides/schemas/create_presentation.json +8 -0
  226. package/integrations/google-slides/schemas/create_slide_after_first_match.json +11 -0
  227. package/integrations/google-slides/schemas/get_page_thumbnail.json +12 -0
  228. package/integrations/google-slides/schemas/get_presentation.json +9 -0
  229. package/integrations/google-slides/schemas/insert_image_after_first_match.json +13 -0
  230. package/integrations/google-slides/schemas/insert_shape_after_first_match.json +13 -0
  231. package/integrations/google-slides/schemas/replace_text_first_match.json +12 -0
  232. package/integrations/google-slides/schemas/set_background_color_for_slide_index.json +11 -0
  233. package/integrations/google-slides/schemas/style_text_first_match.json +12 -0
  234. package/integrations/new_integration_prompt.md +41 -0
  235. package/integrations/notion/__tests__/get_handlers.test.ts +153 -0
  236. package/integrations/notion/__tests__/usage_parity.test.ts +34 -0
  237. package/integrations/notion/__tests__/write_and_admin_handlers.test.ts +190 -0
  238. package/integrations/notion/credentials.json +21 -0
  239. package/integrations/notion/credentials_hint.md +5 -0
  240. package/integrations/notion/handlers/append_block_children.js +7 -0
  241. package/integrations/notion/handlers/create_comment.js +10 -0
  242. package/integrations/notion/handlers/create_database.js +11 -0
  243. package/integrations/notion/handlers/create_page.js +13 -0
  244. package/integrations/notion/handlers/delete_block.js +8 -0
  245. package/integrations/notion/handlers/get_me.js +4 -0
  246. package/integrations/notion/handlers/list_block_children.js +10 -0
  247. package/integrations/notion/handlers/list_comments.js +14 -0
  248. package/integrations/notion/handlers/list_users.js +10 -0
  249. package/integrations/notion/handlers/query_database.js +10 -0
  250. package/integrations/notion/handlers/retrieve_block.js +4 -0
  251. package/integrations/notion/handlers/retrieve_database.js +4 -0
  252. package/integrations/notion/handlers/retrieve_page.js +4 -0
  253. package/integrations/notion/handlers/retrieve_page_property_item.js +10 -0
  254. package/integrations/notion/handlers/retrieve_user.js +4 -0
  255. package/integrations/notion/handlers/search.js +11 -0
  256. package/integrations/notion/handlers/update_block.js +7 -0
  257. package/integrations/notion/handlers/update_database.js +10 -0
  258. package/integrations/notion/handlers/update_page_properties.js +10 -0
  259. package/integrations/notion/manifest.json +139 -0
  260. package/integrations/notion/prompt.md +26 -0
  261. package/integrations/notion/schemas/append_block_children.json +10 -0
  262. package/integrations/notion/schemas/create_comment.json +18 -0
  263. package/integrations/notion/schemas/create_database.json +18 -0
  264. package/integrations/notion/schemas/create_page.json +22 -0
  265. package/integrations/notion/schemas/delete_block.json +9 -0
  266. package/integrations/notion/schemas/empty.json +6 -0
  267. package/integrations/notion/schemas/id_block.json +9 -0
  268. package/integrations/notion/schemas/id_database.json +9 -0
  269. package/integrations/notion/schemas/id_page.json +9 -0
  270. package/integrations/notion/schemas/id_user.json +9 -0
  271. package/integrations/notion/schemas/list_block_children.json +11 -0
  272. package/integrations/notion/schemas/list_comments.json +15 -0
  273. package/integrations/notion/schemas/list_users.json +9 -0
  274. package/integrations/notion/schemas/query_database.json +13 -0
  275. package/integrations/notion/schemas/retrieve_page_property_item.json +12 -0
  276. package/integrations/notion/schemas/search.json +27 -0
  277. package/integrations/notion/schemas/update_block.json +10 -0
  278. package/integrations/notion/schemas/update_database.json +13 -0
  279. package/integrations/notion/schemas/update_page_properties.json +13 -0
  280. package/integrations/trello/__tests__/get_handlers.test.ts +240 -0
  281. package/integrations/trello/__tests__/usage_parity.test.ts +34 -0
  282. package/integrations/trello/__tests__/write_and_admin_handlers.test.ts +189 -0
  283. package/integrations/trello/credentials.json +26 -0
  284. package/integrations/trello/credentials_hint.md +4 -0
  285. package/integrations/trello/handlers/add_checklist_to_card.js +5 -0
  286. package/integrations/trello/handlers/add_member_to_card.js +5 -0
  287. package/integrations/trello/handlers/archive_list.js +5 -0
  288. package/integrations/trello/handlers/create_card.js +13 -0
  289. package/integrations/trello/handlers/create_list.js +7 -0
  290. package/integrations/trello/handlers/delete_card.js +9 -0
  291. package/integrations/trello/handlers/get_board.js +4 -0
  292. package/integrations/trello/handlers/get_board_cards.js +4 -0
  293. package/integrations/trello/handlers/get_board_custom_fields.js +4 -0
  294. package/integrations/trello/handlers/get_board_labels.js +4 -0
  295. package/integrations/trello/handlers/get_board_lists.js +4 -0
  296. package/integrations/trello/handlers/get_board_members.js +4 -0
  297. package/integrations/trello/handlers/get_board_memberships.js +4 -0
  298. package/integrations/trello/handlers/get_card.js +4 -0
  299. package/integrations/trello/handlers/get_card_actions.js +4 -0
  300. package/integrations/trello/handlers/get_card_attachments.js +4 -0
  301. package/integrations/trello/handlers/get_card_checklists.js +4 -0
  302. package/integrations/trello/handlers/get_card_custom_field_items.js +4 -0
  303. package/integrations/trello/handlers/get_card_members.js +4 -0
  304. package/integrations/trello/handlers/get_list.js +4 -0
  305. package/integrations/trello/handlers/get_list_cards.js +4 -0
  306. package/integrations/trello/handlers/get_member.js +4 -0
  307. package/integrations/trello/handlers/get_member_boards.js +4 -0
  308. package/integrations/trello/handlers/get_member_organizations.js +4 -0
  309. package/integrations/trello/handlers/get_organization.js +4 -0
  310. package/integrations/trello/handlers/get_organization_boards.js +4 -0
  311. package/integrations/trello/handlers/move_card_to_list.js +5 -0
  312. package/integrations/trello/handlers/remove_member_from_card.js +9 -0
  313. package/integrations/trello/handlers/search.js +5 -0
  314. package/integrations/trello/handlers/update_card.js +19 -0
  315. package/integrations/trello/handlers/update_list.js +11 -0
  316. package/integrations/trello/manifest.json +231 -0
  317. package/integrations/trello/schemas/add_checklist_to_card.json +10 -0
  318. package/integrations/trello/schemas/add_member_to_card.json +10 -0
  319. package/integrations/trello/schemas/archive_list.json +9 -0
  320. package/integrations/trello/schemas/create_card.json +13 -0
  321. package/integrations/trello/schemas/create_list.json +11 -0
  322. package/integrations/trello/schemas/delete_card.json +9 -0
  323. package/integrations/trello/schemas/display_trello_cards.json +45 -0
  324. package/integrations/trello/schemas/empty.json +5 -0
  325. package/integrations/trello/schemas/get_member.json +5 -0
  326. package/integrations/trello/schemas/id_board.json +8 -0
  327. package/integrations/trello/schemas/id_card.json +8 -0
  328. package/integrations/trello/schemas/id_list.json +8 -0
  329. package/integrations/trello/schemas/id_org.json +8 -0
  330. package/integrations/trello/schemas/move_card_to_list.json +10 -0
  331. package/integrations/trello/schemas/remove_member_from_card.json +10 -0
  332. package/integrations/trello/schemas/search.json +8 -0
  333. package/integrations/trello/schemas/update_card.json +16 -0
  334. package/integrations/trello/schemas/update_list.json +12 -0
  335. package/package.json +45 -0
@@ -0,0 +1,72 @@
1
+ import { beforeAll, describe, expect, it } from 'vitest'
2
+ import { IntegrationProxy } from '../../../src/integrations/proxy.js'
3
+ import { loadIntegrationTools } from '../../../src/integrations/dataLoader.js'
4
+
5
+ // LIVE Google Docs read tests using managed OAuth
6
+ // Required env vars:
7
+ // - COMMANDABLE_MANAGED_OAUTH_BASE_URL
8
+ // - COMMANDABLE_MANAGED_OAUTH_SECRET_KEY
9
+ // - GDOCS_TEST_CONNECTION_ID (managed OAuth connection for provider 'google-docs')
10
+ // - GDOCS_TEST_DOCUMENT_ID (an accessible document ID)
11
+
12
+ const env = process.env as Record<string, string>
13
+ const hasEnv = (...keys: string[]) => keys.every(k => !!env[k] && env[k].trim().length > 0)
14
+ const suite = hasEnv(
15
+ 'COMMANDABLE_MANAGED_OAUTH_BASE_URL',
16
+ 'COMMANDABLE_MANAGED_OAUTH_SECRET_KEY',
17
+ 'GDOCS_TEST_CONNECTION_ID',
18
+ )
19
+ ? describe
20
+ : describe.skip
21
+
22
+ suite('google-docs read handlers (live)', () => {
23
+ let buildReadHandler: (name: string) => ((input: any) => Promise<any>)
24
+
25
+ beforeAll(async () => {
26
+ const { COMMANDABLE_MANAGED_OAUTH_BASE_URL, COMMANDABLE_MANAGED_OAUTH_SECRET_KEY, GDOCS_TEST_CONNECTION_ID } = env
27
+
28
+ const proxy = new IntegrationProxy({
29
+ managedOAuthBaseUrl: COMMANDABLE_MANAGED_OAUTH_BASE_URL,
30
+ managedOAuthSecretKey: COMMANDABLE_MANAGED_OAUTH_SECRET_KEY,
31
+ })
32
+ const integrationNode = { id: 'node-gdocs', type: 'google-docs', label: 'Google Docs', connectionId: GDOCS_TEST_CONNECTION_ID } as any
33
+
34
+ const tools = loadIntegrationTools('google-docs')
35
+ expect(tools).toBeTruthy()
36
+
37
+ buildReadHandler = (name: string) => {
38
+ const tool = tools!.read.find(t => t.name === name)
39
+ expect(tool, `read tool ${name} exists`).toBeTruthy()
40
+ const integration = { fetch: (path: string, init?: RequestInit) => proxy.call(integrationNode, path, init) }
41
+ const build = new Function('integration', `return (${tool!.handlerCode});`)
42
+ return build(integration) as (input: any) => Promise<any>
43
+ }
44
+ }, 60000)
45
+
46
+ it('get_document returns metadata/content', async () => {
47
+ const documentId = env.GDOCS_TEST_DOCUMENT_ID
48
+ if (!documentId)
49
+ return expect(true).toBe(true)
50
+ const handler = buildReadHandler('get_document')
51
+ const result = await handler({ documentId })
52
+ expect(result?.documentId || result?.body?.content || result?.title).toBeTruthy()
53
+ }, 30000)
54
+
55
+ it('get_document_text returns plain text', async () => {
56
+ const documentId = env.GDOCS_TEST_DOCUMENT_ID
57
+ if (!documentId)
58
+ return expect(true).toBe(true)
59
+ const handler = buildReadHandler('get_document_text')
60
+ const result = await handler({ documentId })
61
+ expect(typeof result?.text === 'string').toBe(true)
62
+ }, 30000)
63
+
64
+ it('get_document_structured returns body JSON', async () => {
65
+ const documentId = env.GDOCS_TEST_DOCUMENT_ID
66
+ if (!documentId)
67
+ return expect(true).toBe(true)
68
+ const handler = buildReadHandler('get_document_structured')
69
+ const result = await handler({ documentId })
70
+ expect(result?.body || result?.documentId).toBeTruthy()
71
+ }, 30000)
72
+ })
@@ -0,0 +1,34 @@
1
+ import { existsSync, readdirSync, readFileSync } from 'node:fs'
2
+ import { resolve } from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+ import { describe, expect, it } from 'vitest'
5
+ import { loadIntegrationManifest } from '../../../src/integrations/dataLoader.js'
6
+
7
+ function escapeRegExp(str: string): string {
8
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
9
+ }
10
+
11
+ describe('google-docs static usage parity', () => {
12
+ it('every manifest tool is referenced in tests via build*(name)', () => {
13
+ const manifest = loadIntegrationManifest('google-docs')!
14
+ const toolNames = (manifest.tools as any[]).map(t => t.name)
15
+
16
+ const testsDir = fileURLToPath(new URL('.', import.meta.url))
17
+ expect(existsSync(testsDir)).toBe(true)
18
+ const testFiles = readdirSync(testsDir)
19
+ .filter(f => /\.test\.(t|j)s$/.test(f) && !f.includes('usage_parity.test'))
20
+ .map(f => resolve(testsDir, f))
21
+
22
+ const fileContents = testFiles.map(f => readFileSync(f, 'utf8'))
23
+
24
+ const missing: string[] = []
25
+ for (const name of toolNames) {
26
+ const nameRe = new RegExp(`build(?:Read|Write|Admin)?(?:Handler)?\\(\\s*['\"\`]${escapeRegExp(name)}['\"\`]\\s*\\)`, 'm')
27
+ const found = fileContents.some(src => nameRe.test(src))
28
+ if (!found)
29
+ missing.push(name)
30
+ }
31
+
32
+ expect(missing, `Missing handler usages in tests: ${missing.join(', ')}`).toEqual([])
33
+ })
34
+ })
@@ -0,0 +1,249 @@
1
+ import { beforeAll, describe, expect, it } from 'vitest'
2
+ import { IntegrationProxy } from '../../../src/integrations/proxy.js'
3
+ import { loadIntegrationTools } from '../../../src/integrations/dataLoader.js'
4
+
5
+ // LIVE Google Docs write tests using managed OAuth
6
+ // Required env vars:
7
+ // - COMMANDABLE_MANAGED_OAUTH_BASE_URL
8
+ // - COMMANDABLE_MANAGED_OAUTH_SECRET_KEY
9
+ // - GDOCS_TEST_CONNECTION_ID (managed OAuth connection for provider 'google-docs')
10
+ // - GDOCS_TEST_DOCUMENT_ID (target document ID with write access) OR GDOCS_ALLOW_CREATE to create
11
+
12
+ interface Ctx {
13
+ documentId?: string
14
+ }
15
+
16
+ const env = process.env as Record<string, string>
17
+ const hasEnv = (...keys: string[]) => keys.every(k => !!env[k] && env[k].trim().length > 0)
18
+ const suite = hasEnv(
19
+ 'COMMANDABLE_MANAGED_OAUTH_BASE_URL',
20
+ 'COMMANDABLE_MANAGED_OAUTH_SECRET_KEY',
21
+ 'GDOCS_TEST_CONNECTION_ID',
22
+ )
23
+ ? describe
24
+ : describe.skip
25
+
26
+ suite('google-docs write handlers (live)', () => {
27
+ const ctx: Ctx = {}
28
+ let buildWriteHandler: (name: string) => ((input: any) => Promise<any>)
29
+ let buildReadHandler: (name: string) => ((input: any) => Promise<any>)
30
+
31
+ beforeAll(async () => {
32
+ const { COMMANDABLE_MANAGED_OAUTH_BASE_URL, COMMANDABLE_MANAGED_OAUTH_SECRET_KEY, GDOCS_TEST_CONNECTION_ID, GDOCS_TEST_DOCUMENT_ID } = env
33
+
34
+ const proxy = new IntegrationProxy({
35
+ managedOAuthBaseUrl: COMMANDABLE_MANAGED_OAUTH_BASE_URL,
36
+ managedOAuthSecretKey: COMMANDABLE_MANAGED_OAUTH_SECRET_KEY,
37
+ })
38
+ const integrationNode = { id: 'node-gdocs', type: 'google-docs', label: 'Google Docs', connectionId: GDOCS_TEST_CONNECTION_ID } as any
39
+
40
+ const tools = loadIntegrationTools('google-docs')
41
+ expect(tools).toBeTruthy()
42
+
43
+ buildWriteHandler = (name: string) => {
44
+ const tool = tools!.write.find(t => t.name === name)
45
+ expect(tool, `write tool ${name} exists`).toBeTruthy()
46
+ const integration = { fetch: (path: string, init?: RequestInit) => proxy.call(integrationNode, path, init) }
47
+ const build = new Function('integration', `return (${tool!.handlerCode});`)
48
+ return build(integration) as (input: any) => Promise<any>
49
+ }
50
+
51
+ buildReadHandler = (name: string) => {
52
+ const tool = tools!.read.find(t => t.name === name)
53
+ expect(tool, `read tool ${name} exists`).toBeTruthy()
54
+ const integration = { fetch: (path: string, init?: RequestInit) => proxy.call(integrationNode, path, init) }
55
+ const build = new Function('integration', `return (${tool!.handlerCode});`)
56
+ return build(integration) as (input: any) => Promise<any>
57
+ }
58
+
59
+ ctx.documentId = GDOCS_TEST_DOCUMENT_ID
60
+ }, 60000)
61
+
62
+ it('create_document creates a document when allowed', async () => {
63
+ if (!process.env.GDOCS_ALLOW_CREATE)
64
+ return expect(true).toBe(true)
65
+ const create_document = buildWriteHandler('create_document')
66
+ const res = await create_document({ title: `CmdTest Doc ${Date.now()}` })
67
+ expect(res?.documentId).toBeTruthy()
68
+ }, 60000)
69
+
70
+ it('batch_update can perform a trivial replaceAllText no-op', async () => {
71
+ const documentId = process.env.GDOCS_TEST_DOCUMENT_ID
72
+ if (!documentId)
73
+ return expect(true).toBe(true)
74
+ const batch_update = buildWriteHandler('batch_update')
75
+ const res = await batch_update({ documentId, requests: [
76
+ { replaceAllText: { containsText: { text: '___unlikely___', matchCase: true }, replaceText: '___unlikely___' } },
77
+ ] })
78
+ expect(Array.isArray(res?.replies) || res?.documentId).toBeTruthy()
79
+ }, 60000)
80
+
81
+ it('append_text appends content', async () => {
82
+ const documentId = process.env.GDOCS_TEST_DOCUMENT_ID
83
+ if (!documentId)
84
+ return expect(true).toBe(true)
85
+ const append_text = buildWriteHandler('append_text')
86
+ const marker = `CmdTest ${Date.now()}`
87
+ const res = await append_text({ documentId, text: marker })
88
+ expect(res?.documentId || Array.isArray(res?.replies)).toBeTruthy()
89
+ const get_text = buildReadHandler('get_document_text')
90
+ const after = await get_text({ documentId })
91
+ expect(String(after?.text || '')).toContain(marker)
92
+ }, 60000)
93
+
94
+ it('insert_text_after_first_match inserts text near target', async () => {
95
+ const documentId = process.env.GDOCS_TEST_DOCUMENT_ID
96
+ if (!documentId)
97
+ return expect(true).toBe(true)
98
+ const insert_text_after_first_match = buildWriteHandler('insert_text_after_first_match')
99
+ const get_text = buildReadHandler('get_document_text')
100
+ const anchor = `ANCHOR_${Date.now()}`
101
+ const appended = buildWriteHandler('append_text')
102
+ const before = await get_text({ documentId })
103
+ if (!String(before?.text || '').includes(anchor)) {
104
+ await appended({ documentId, text: `\n${anchor}\n` })
105
+ }
106
+ const insertSnippet = ` CmdTest ${Date.now()} `
107
+ const res = await insert_text_after_first_match({ documentId, findText: anchor, insertText: insertSnippet, position: 'after' })
108
+ expect(res?.applied === true || Array.isArray(res?.replies)).toBeTruthy()
109
+ const after = await get_text({ documentId })
110
+ const text = String(after?.text || '')
111
+ expect(text).toContain(anchor)
112
+ expect(text).toContain(insertSnippet)
113
+ }, 60000)
114
+
115
+ it('replace_all_text replaces occurrences', async () => {
116
+ const documentId = process.env.GDOCS_TEST_DOCUMENT_ID
117
+ if (!documentId)
118
+ return expect(true).toBe(true)
119
+ const replace_all_text = buildWriteHandler('replace_all_text')
120
+ const res = await replace_all_text({ documentId, findText: '___unlikely___', replaceText: '___unlikely___', matchCase: true })
121
+ expect(res?.documentId || Array.isArray(res?.replies)).toBeTruthy()
122
+ }, 60000)
123
+
124
+ it('style_first_match applies style to first match', async () => {
125
+ const documentId = process.env.GDOCS_TEST_DOCUMENT_ID
126
+ if (!documentId)
127
+ return expect(true).toBe(true)
128
+ const style_first_match = buildWriteHandler('style_first_match')
129
+ const get_struct = buildReadHandler('get_document_structured')
130
+ const anchor = `ANCHOR_${Date.now()}`
131
+ const appended = buildWriteHandler('append_text')
132
+ const before = await get_struct({ documentId })
133
+ const hasAnchorBefore = JSON.stringify(before?.body || {}).includes(anchor)
134
+ if (!hasAnchorBefore)
135
+ await appended({ documentId, text: `\n${anchor}\n` })
136
+ const res = await style_first_match({ documentId, findText: anchor, textStyle: { bold: true } })
137
+ expect(res?.applied === true || Array.isArray(res?.replies)).toBeTruthy()
138
+ }, 60000)
139
+
140
+ it('insert_table_after_first_match inserts a table near target', async () => {
141
+ const documentId = process.env.GDOCS_TEST_DOCUMENT_ID
142
+ if (!documentId)
143
+ return expect(true).toBe(true)
144
+ const insert_table_after_first_match = buildWriteHandler('insert_table_after_first_match')
145
+ const get_struct = buildReadHandler('get_document_structured')
146
+ const anchor = `ANCHOR_${Date.now()}`
147
+ const appended = buildWriteHandler('append_text')
148
+ const before = await get_struct({ documentId })
149
+ const hasAnchorBefore = JSON.stringify(before?.body || {}).includes(anchor)
150
+ if (!hasAnchorBefore)
151
+ await appended({ documentId, text: `\n${anchor}\n` })
152
+ const res = await insert_table_after_first_match({ documentId, findText: anchor, rows: 1, columns: 1 })
153
+ expect(res?.applied === true || Array.isArray(res?.replies)).toBeTruthy()
154
+ const after = await get_struct({ documentId })
155
+ const hasTable = (after?.body?.content || []).some((el: any) => Boolean(el.table))
156
+ expect(hasTable).toBe(true)
157
+ }, 60000)
158
+
159
+ it('insert_page_break_after_first_match inserts a break near target', async () => {
160
+ const documentId = process.env.GDOCS_TEST_DOCUMENT_ID
161
+ if (!documentId)
162
+ return expect(true).toBe(true)
163
+ const insert_page_break_after_first_match = buildWriteHandler('insert_page_break_after_first_match')
164
+ const get_struct = buildReadHandler('get_document_structured')
165
+ const anchor = `ANCHOR_${Date.now()}`
166
+ const appended = buildWriteHandler('append_text')
167
+ const before = await get_struct({ documentId })
168
+ const hasAnchorBefore = JSON.stringify(before?.body || {}).includes(anchor)
169
+ if (!hasAnchorBefore)
170
+ await appended({ documentId, text: `\n${anchor}\n` })
171
+ const res = await insert_page_break_after_first_match({ documentId, findText: anchor })
172
+ expect(res?.applied === true || Array.isArray(res?.replies)).toBeTruthy()
173
+ const after = await get_struct({ documentId })
174
+ const hasBreak = (after?.body?.content || []).some((el: any) => Boolean(el.sectionBreak))
175
+ expect(hasBreak).toBe(true)
176
+ }, 60000)
177
+
178
+ it('insert_inline_image_after_first_match inserts an image when allowed', async () => {
179
+ if (!process.env.GDOCS_TEST_DOCUMENT_ID || !process.env.GDOCS_TEST_IMAGE_URI)
180
+ return expect(true).toBe(true)
181
+ const documentId = process.env.GDOCS_TEST_DOCUMENT_ID
182
+ const insert_inline_image_after_first_match = buildWriteHandler('insert_inline_image_after_first_match')
183
+ const anchor = `ANCHOR_${Date.now()}`
184
+ const appended = buildWriteHandler('append_text')
185
+ const get_text = buildReadHandler('get_document_text')
186
+ const before = await get_text({ documentId })
187
+ if (!String(before?.text || '').includes(anchor))
188
+ await appended({ documentId, text: `\n${anchor}\n` })
189
+ const res = await insert_inline_image_after_first_match({ documentId, findText: anchor, uri: process.env.GDOCS_TEST_IMAGE_URI!, altText: 'CmdTest' })
190
+ expect(res?.applied === true || Array.isArray(res?.replies)).toBeTruthy()
191
+ }, 60000)
192
+
193
+ it('delete_first_match deletes a small span (no-op ok)', async () => {
194
+ const documentId = process.env.GDOCS_TEST_DOCUMENT_ID
195
+ if (!documentId)
196
+ return expect(true).toBe(true)
197
+ const delete_first_match = buildWriteHandler('delete_first_match')
198
+ const get_text = buildReadHandler('get_document_text')
199
+ const anchor = `ANCHOR_${Date.now()}`
200
+ const appended = buildWriteHandler('append_text')
201
+ const before = await get_text({ documentId })
202
+ if (!String(before?.text || '').includes(anchor))
203
+ await appended({ documentId, text: `\n${anchor}\n` })
204
+ const res = await delete_first_match({ documentId, findText: anchor })
205
+ expect(res?.applied === true || Array.isArray(res?.replies)).toBeTruthy()
206
+ const after = await get_text({ documentId })
207
+ expect(String(after?.text || '')).not.toContain(anchor)
208
+ }, 60000)
209
+
210
+ it('update_paragraph_style_for_first_match updates paragraph style near target', async () => {
211
+ const documentId = process.env.GDOCS_TEST_DOCUMENT_ID
212
+ if (!documentId)
213
+ return expect(true).toBe(true)
214
+ const update_paragraph_style_for_first_match = buildWriteHandler('update_paragraph_style_for_first_match')
215
+ const get_struct = buildReadHandler('get_document_structured')
216
+ const anchor = `ANCHOR_${Date.now()}`
217
+ const appended = buildWriteHandler('append_text')
218
+ const before = await get_struct({ documentId })
219
+ const hasAnchorBefore = JSON.stringify(before?.body || {}).includes(anchor)
220
+ if (!hasAnchorBefore)
221
+ await appended({ documentId, text: `\n${anchor}\n` })
222
+ const res = await update_paragraph_style_for_first_match({ documentId, findText: anchor, paragraphStyle: { alignment: 'CENTER' } })
223
+ expect(res?.applied === true || Array.isArray(res?.replies)).toBeTruthy()
224
+ const after = await get_struct({ documentId })
225
+ // find the paragraph containing anchor and verify alignment
226
+ let foundAligned = false
227
+ for (const el of (after?.body?.content || [])) {
228
+ if (!el.paragraph)
229
+ continue
230
+ const p = el.paragraph
231
+ const text = (p.elements || []).map((e: any) => e?.textRun?.content || '').join('')
232
+ if (text.includes(anchor)) {
233
+ if (p.paragraphStyle?.alignment === 'CENTER')
234
+ foundAligned = true
235
+ break
236
+ }
237
+ }
238
+ expect(foundAligned).toBe(true)
239
+ }, 60000)
240
+
241
+ it('update_document_style updates doc style with no-op', async () => {
242
+ const documentId = process.env.GDOCS_TEST_DOCUMENT_ID
243
+ if (!documentId)
244
+ return expect(true).toBe(true)
245
+ const update_document_style = buildWriteHandler('update_document_style')
246
+ const res = await update_document_style({ documentId, documentStyle: { useFirstPageHeaderFooter: false } })
247
+ expect(res?.documentId || Array.isArray(res?.replies)).toBeTruthy()
248
+ }, 60000)
249
+ })
@@ -0,0 +1,36 @@
1
+ {
2
+ "schema": {
3
+ "type": "object",
4
+ "properties": {
5
+ "token": {
6
+ "type": "string",
7
+ "title": "OAuth Access Token (optional)",
8
+ "description": "Google OAuth access token to use as a Bearer token (typically short-lived)."
9
+ },
10
+ "serviceAccountJson": {
11
+ "type": "string",
12
+ "title": "Service Account JSON (recommended)",
13
+ "description": "Full service account key JSON (contents of the downloaded JSON file)."
14
+ },
15
+ "subject": {
16
+ "type": "string",
17
+ "title": "Subject / impersonated user (optional)",
18
+ "description": "Optional user email to impersonate when using Google Workspace domain-wide delegation."
19
+ },
20
+ "scopes": {
21
+ "type": "array",
22
+ "title": "OAuth scopes (optional)",
23
+ "description": "Optional override for OAuth scopes.",
24
+ "items": { "type": "string" }
25
+ }
26
+ },
27
+ "required": [],
28
+ "additionalProperties": false
29
+ },
30
+ "injection": {
31
+ "headers": {
32
+ "Authorization": "Bearer {{token}}"
33
+ }
34
+ }
35
+ }
36
+
@@ -0,0 +1,9 @@
1
+ Recommended: use a Google service account.
2
+
3
+ - Create a service account in Google Cloud
4
+ - Download a JSON key
5
+ - Paste the JSON into `serviceAccountJson` (or use `env:GOOGLE_SERVICE_ACCOUNT_JSON`)
6
+ - Share your test document with the service account `client_email`
7
+
8
+ You can also paste a short-lived OAuth access token into `token`, but it will expire.
9
+
@@ -0,0 +1,12 @@
1
+ async (input) => {
2
+ const { documentId, text } = input
3
+ // Get doc to find end index
4
+ const metaRes = await integration.fetch(`/documents/${encodeURIComponent(documentId)}`)
5
+ const meta = await metaRes.json()
6
+ const endIndex = meta?.body?.content?.[meta.body.content.length - 1]?.endIndex || 1
7
+ const res = await integration.fetch(`/documents/${encodeURIComponent(documentId)}:batchUpdate`, {
8
+ method: 'POST',
9
+ body: { requests: [{ insertText: { text, location: { index: endIndex - 1 } } }] },
10
+ })
11
+ return await res.json()
12
+ }
@@ -0,0 +1,13 @@
1
+ async (input) => {
2
+ const { documentId, requests, writeControl, includeTabStops } = input
3
+ const params = new URLSearchParams()
4
+ if (includeTabStops !== undefined)
5
+ params.set('includeTabStops', String(includeTabStops))
6
+ const qs = params.toString()
7
+ const path = `/documents/${encodeURIComponent(documentId)}:batchUpdate${qs ? `?${qs}` : ''}`
8
+ const body = { requests }
9
+ if (writeControl)
10
+ body.writeControl = writeControl
11
+ const res = await integration.fetch(path, { method: 'POST', body })
12
+ return await res.json()
13
+ }
@@ -0,0 +1,9 @@
1
+ async (input) => {
2
+ const { title, ...rest } = input
3
+ const body = {}
4
+ if (title !== undefined)
5
+ body.title = title
6
+ Object.assign(body, rest)
7
+ const res = await integration.fetch(`/documents`, { method: 'POST', body })
8
+ return await res.json()
9
+ }
@@ -0,0 +1,50 @@
1
+ async (input) => {
2
+ const { documentId, findText } = input
3
+ const marker = `__CMD_MARK_${Date.now()}__`
4
+ const replaceRes = await integration.fetch(`/documents/${encodeURIComponent(documentId)}:batchUpdate`, {
5
+ method: 'POST',
6
+ body: { requests: [{ replaceAllText: { containsText: { text: findText, matchCase: false }, replaceText: marker } }] },
7
+ })
8
+ await replaceRes.json()
9
+
10
+ const getRes = await integration.fetch(`/documents/${encodeURIComponent(documentId)}`)
11
+ const doc = await getRes.json()
12
+ let startIndex = -1
13
+ let endIndex = -1
14
+ for (const el of (doc?.body?.content || [])) {
15
+ const p = el.paragraph
16
+ if (!p)
17
+ continue
18
+ for (const e of (p.elements || [])) {
19
+ const t = e?.textRun?.content
20
+ if (!t)
21
+ continue
22
+ const idx = t.indexOf(marker)
23
+ if (idx >= 0) {
24
+ const elStart = e.startIndex || 1
25
+ startIndex = elStart + idx
26
+ endIndex = startIndex + marker.length
27
+ break
28
+ }
29
+ }
30
+ if (startIndex >= 0)
31
+ break
32
+ }
33
+ if (startIndex < 0) {
34
+ const confirm = await integration.fetch(`/documents/${encodeURIComponent(documentId)}`)
35
+ const got = await confirm.json()
36
+ return { documentId: got?.documentId || documentId, applied: false, replies: [] }
37
+ }
38
+
39
+ const requests = []
40
+ requests.push({ deleteContentRange: { range: { startIndex, endIndex } } })
41
+ // also clean any remaining markers
42
+ requests.push({ replaceAllText: { containsText: { text: marker, matchCase: true }, replaceText: '' } })
43
+ const res = await integration.fetch(`/documents/${encodeURIComponent(documentId)}:batchUpdate`, { method: 'POST', body: { requests } })
44
+ const out = await res.json()
45
+ if (out?.documentId || Array.isArray(out?.replies))
46
+ return { ...out, applied: true }
47
+ const confirm = await integration.fetch(`/documents/${encodeURIComponent(documentId)}`)
48
+ const got = await confirm.json()
49
+ return { documentId: got?.documentId || documentId, applied: true, replies: Array.isArray(out?.replies) ? out.replies : [] }
50
+ }
@@ -0,0 +1,12 @@
1
+ async (input) => {
2
+ const { documentId, suggestionsViewMode, includeTabsAndSpaces } = input
3
+ const params = new URLSearchParams()
4
+ if (suggestionsViewMode)
5
+ params.set('suggestionsViewMode', String(suggestionsViewMode))
6
+ if (includeTabsAndSpaces !== undefined)
7
+ params.set('includeTabsAndSpaces', String(includeTabsAndSpaces))
8
+ const qs = params.toString()
9
+ const path = `/documents/${encodeURIComponent(documentId)}${qs ? `?${qs}` : ''}`
10
+ const res = await integration.fetch(path)
11
+ return await res.json()
12
+ }
@@ -0,0 +1,6 @@
1
+ async (input) => {
2
+ const { documentId } = input
3
+ const res = await integration.fetch(`/documents/${encodeURIComponent(documentId)}`)
4
+ const doc = await res.json()
5
+ return { documentId: doc?.documentId || documentId, body: doc?.body }
6
+ }
@@ -0,0 +1,17 @@
1
+ async (input) => {
2
+ const { documentId } = input
3
+ const res = await integration.fetch(`/documents/${encodeURIComponent(documentId)}`)
4
+ const doc = await res.json()
5
+ const content = doc?.body?.content || []
6
+ let text = ''
7
+ for (const el of content) {
8
+ const paragraphs = el.paragraph ? [el.paragraph] : []
9
+ for (const p of paragraphs) {
10
+ for (const e of p.elements || []) {
11
+ text += e.textRun?.content || ''
12
+ }
13
+ text += '\n'
14
+ }
15
+ }
16
+ return { documentId: doc?.documentId || documentId, text }
17
+ }
@@ -0,0 +1,41 @@
1
+ async (input) => {
2
+ const { documentId, findText, uri, altText, position } = input
3
+ const marker = `__CMD_MARK_${Date.now()}__`
4
+ const replaceRes = await integration.fetch(`/documents/${encodeURIComponent(documentId)}:batchUpdate`, {
5
+ method: 'POST',
6
+ body: { requests: [{ replaceAllText: { containsText: { text: findText, matchCase: false }, replaceText: marker } }] },
7
+ })
8
+ await replaceRes.json()
9
+
10
+ const getRes = await integration.fetch(`/documents/${encodeURIComponent(documentId)}`)
11
+ const doc = await getRes.json()
12
+ let baseIndex = -1
13
+ for (const el of (doc?.body?.content || [])) {
14
+ const p = el.paragraph
15
+ if (!p)
16
+ continue
17
+ for (const e of (p.elements || [])) {
18
+ const t = e?.textRun?.content
19
+ if (!t)
20
+ continue
21
+ const idx = t.indexOf(marker)
22
+ if (idx >= 0) {
23
+ const elStart = e.startIndex || 1
24
+ const startIndex = elStart + idx
25
+ const endIndex = startIndex + marker.length
26
+ baseIndex = position === 'before' ? startIndex : endIndex
27
+ break
28
+ }
29
+ }
30
+ if (baseIndex >= 0)
31
+ break
32
+ }
33
+ if (baseIndex < 0)
34
+ return { ok: true }
35
+
36
+ const requests = []
37
+ requests.push({ insertInlineImage: { location: { index: baseIndex }, uri, altTextTitle: altText } })
38
+ requests.push({ replaceAllText: { containsText: { text: marker, matchCase: true }, replaceText: findText } })
39
+ const res = await integration.fetch(`/documents/${encodeURIComponent(documentId)}:batchUpdate`, { method: 'POST', body: { requests } })
40
+ return await res.json()
41
+ }
@@ -0,0 +1,49 @@
1
+ async (input) => {
2
+ const { documentId, findText, position } = input
3
+ const marker = `__CMD_MARK_${Date.now()}__`
4
+ const replaceRes = await integration.fetch(`/documents/${encodeURIComponent(documentId)}:batchUpdate`, {
5
+ method: 'POST',
6
+ body: { requests: [{ replaceAllText: { containsText: { text: findText, matchCase: false }, replaceText: marker } }] },
7
+ })
8
+ await replaceRes.json()
9
+
10
+ const getRes = await integration.fetch(`/documents/${encodeURIComponent(documentId)}`)
11
+ const doc = await getRes.json()
12
+ let baseIndex = -1
13
+ for (const el of (doc?.body?.content || [])) {
14
+ const p = el.paragraph
15
+ if (!p)
16
+ continue
17
+ for (const e of (p.elements || [])) {
18
+ const t = e?.textRun?.content
19
+ if (!t)
20
+ continue
21
+ const idx = t.indexOf(marker)
22
+ if (idx >= 0) {
23
+ const elStart = e.startIndex || 1
24
+ const startIndex = elStart + idx
25
+ const endIndex = startIndex + marker.length
26
+ baseIndex = position === 'before' ? startIndex : endIndex
27
+ break
28
+ }
29
+ }
30
+ if (baseIndex >= 0)
31
+ break
32
+ }
33
+ if (baseIndex < 0) {
34
+ const confirm = await integration.fetch(`/documents/${encodeURIComponent(documentId)}`)
35
+ const got = await confirm.json()
36
+ return { documentId: got?.documentId || documentId, applied: false, replies: [] }
37
+ }
38
+
39
+ const requests = []
40
+ requests.push({ insertPageBreak: { location: { index: baseIndex } } })
41
+ requests.push({ replaceAllText: { containsText: { text: marker, matchCase: true }, replaceText: findText } })
42
+ const res = await integration.fetch(`/documents/${encodeURIComponent(documentId)}:batchUpdate`, { method: 'POST', body: { requests } })
43
+ const out = await res.json()
44
+ if (out?.documentId || Array.isArray(out?.replies))
45
+ return { ...out, applied: true }
46
+ const confirm = await integration.fetch(`/documents/${encodeURIComponent(documentId)}`)
47
+ const got = await confirm.json()
48
+ return { documentId: got?.documentId || documentId, applied: true, replies: Array.isArray(out?.replies) ? out.replies : [] }
49
+ }