runline 0.11.6 → 0.13.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 (256) hide show
  1. package/dist/commands/actions.js +3 -1
  2. package/dist/core/engine.js +3 -0
  3. package/dist/index.d.ts +1 -1
  4. package/dist/plugin/api.d.ts +2 -1
  5. package/dist/plugin/types.d.ts +2 -0
  6. package/dist/plugins/_shared/googleSchemas.js +23 -0
  7. package/dist/plugins/actionNetwork/src/index.js +23 -0
  8. package/dist/plugins/activeCampaign/src/index.js +48 -0
  9. package/dist/plugins/adalo/src/index.js +5 -0
  10. package/dist/plugins/affinity/src/index.js +16 -0
  11. package/dist/plugins/agileCrm/src/index.js +15 -0
  12. package/dist/plugins/airtable/src/index.js +10 -0
  13. package/dist/plugins/airtop/src/index.js +24 -0
  14. package/dist/plugins/apiTemplateIo/src/index.js +4 -0
  15. package/dist/plugins/asana/src/index.js +22 -0
  16. package/dist/plugins/autopilot/src/index.js +11 -0
  17. package/dist/plugins/bambooHr/src/index.js +11 -0
  18. package/dist/plugins/bannerbear/src/index.js +4 -0
  19. package/dist/plugins/baserow/src/index.js +8 -0
  20. package/dist/plugins/beeminder/src/index.js +18 -0
  21. package/dist/plugins/bitly/src/index.js +3 -0
  22. package/dist/plugins/bitwarden/src/index.js +19 -0
  23. package/dist/plugins/box/src/index.js +11 -0
  24. package/dist/plugins/brandfetch/src/index.js +5 -0
  25. package/dist/plugins/brevo/src/index.js +15 -0
  26. package/dist/plugins/bubble/src/index.js +5 -0
  27. package/dist/plugins/chargebee/src/index.js +5 -0
  28. package/dist/plugins/circleci/src/index.js +3 -0
  29. package/dist/plugins/ciscoWebex/src/index.js +10 -0
  30. package/dist/plugins/clearbit/src/index.js +3 -0
  31. package/dist/plugins/clickup/src/index.js +61 -0
  32. package/dist/plugins/clockify/src/index.js +25 -0
  33. package/dist/plugins/cloudflare/src/index.js +4 -0
  34. package/dist/plugins/cockpit/src/index.js +5 -0
  35. package/dist/plugins/coda/src/index.js +18 -0
  36. package/dist/plugins/coingecko/src/index.js +10 -0
  37. package/dist/plugins/contentful/src/index.js +7 -0
  38. package/dist/plugins/convertkit/src/index.js +16 -0
  39. package/dist/plugins/copper/src/index.js +7 -0
  40. package/dist/plugins/cortex/src/index.js +4 -0
  41. package/dist/plugins/currents/src/index.js +22 -0
  42. package/dist/plugins/customerIo/src/index.js +9 -0
  43. package/dist/plugins/databricks/src/index.js +34 -0
  44. package/dist/plugins/deepl/src/index.js +2 -0
  45. package/dist/plugins/demio/src/index.js +4 -0
  46. package/dist/plugins/dhl/src/index.js +1 -0
  47. package/dist/plugins/discord/src/index.js +13 -0
  48. package/dist/plugins/discourse/src/index.js +16 -0
  49. package/dist/plugins/disqus/src/index.js +4 -0
  50. package/dist/plugins/docker/src/index.js +5 -0
  51. package/dist/plugins/drift/src/index.js +5 -0
  52. package/dist/plugins/dropbox/src/index.js +9 -0
  53. package/dist/plugins/dropcontact/src/index.js +2 -0
  54. package/dist/plugins/egoi/src/index.js +4 -0
  55. package/dist/plugins/elasticsearch/src/index.js +9 -0
  56. package/dist/plugins/emelia/src/index.js +9 -0
  57. package/dist/plugins/erpnext/src/index.js +5 -0
  58. package/dist/plugins/facebookGraph/src/index.js +1 -0
  59. package/dist/plugins/freshdesk/src/index.js +10 -0
  60. package/dist/plugins/freshservice/src/index.js +7 -0
  61. package/dist/plugins/freshworksCrm/src/index.js +7 -0
  62. package/dist/plugins/getresponse/src/index.js +5 -0
  63. package/dist/plugins/ghost/src/index.js +5 -0
  64. package/dist/plugins/github/src/index.js +37 -0
  65. package/dist/plugins/gitlab/src/index.js +17 -0
  66. package/dist/plugins/gmail/src/index.js +200 -184
  67. package/dist/plugins/gong/src/index.js +4 -0
  68. package/dist/plugins/googleAppsScript/src/index.js +98 -43
  69. package/dist/plugins/googleCalendar/src/index.js +329 -250
  70. package/dist/plugins/googleContacts/src/index.js +144 -145
  71. package/dist/plugins/googleDocs/src/documents.js +31 -38
  72. package/dist/plugins/googleDocs/src/formatting.js +51 -47
  73. package/dist/plugins/googleDocs/src/images.js +23 -26
  74. package/dist/plugins/googleDocs/src/shared.js +55 -0
  75. package/dist/plugins/googleDocs/src/structure.js +111 -123
  76. package/dist/plugins/googleDocs/src/tables.js +103 -154
  77. package/dist/plugins/googleDocs/src/tabs.js +27 -23
  78. package/dist/plugins/googleDocs/src/text.js +106 -136
  79. package/dist/plugins/googleDrive/src/index.js +461 -408
  80. package/dist/plugins/googleImage/src/index.js +14 -16
  81. package/dist/plugins/googleSheets/src/index.js +527 -339
  82. package/dist/plugins/googleSlides/src/index.js +92 -72
  83. package/dist/plugins/googleTasks/src/index.js +94 -92
  84. package/dist/plugins/gotify/src/index.js +3 -0
  85. package/dist/plugins/gotowebinar/src/index.js +20 -0
  86. package/dist/plugins/grafana/src/index.js +17 -0
  87. package/dist/plugins/graphql/src/index.js +2 -0
  88. package/dist/plugins/grist/src/index.js +4 -0
  89. package/dist/plugins/hackernews/src/index.js +6 -0
  90. package/dist/plugins/halopsa/src/index.js +5 -0
  91. package/dist/plugins/harvest/src/index.js +14 -0
  92. package/dist/plugins/helpscout/src/index.js +13 -0
  93. package/dist/plugins/highlevel/src/index.js +17 -0
  94. package/dist/plugins/homeAssistant/src/index.js +13 -0
  95. package/dist/plugins/hubspot/src/index.js +14 -0
  96. package/dist/plugins/humanticAi/src/index.js +3 -0
  97. package/dist/plugins/hunter/src/index.js +3 -0
  98. package/dist/plugins/intercom/src/index.js +10 -0
  99. package/dist/plugins/iterable/src/index.js +6 -0
  100. package/dist/plugins/jenkins/src/index.js +11 -0
  101. package/dist/plugins/jira/src/index.js +16 -0
  102. package/dist/plugins/keap/src/index.js +28 -0
  103. package/dist/plugins/kobotoolbox/src/index.js +17 -0
  104. package/dist/plugins/lemlist/src/index.js +15 -0
  105. package/dist/plugins/linear/src/attachments.js +6 -0
  106. package/dist/plugins/linear/src/comments.js +5 -0
  107. package/dist/plugins/linear/src/cycles.js +2 -0
  108. package/dist/plugins/linear/src/initiatives.js +5 -0
  109. package/dist/plugins/linear/src/issues.js +14 -0
  110. package/dist/plugins/linear/src/labels.js +5 -0
  111. package/dist/plugins/linear/src/organization.js +1 -0
  112. package/dist/plugins/linear/src/projects.js +11 -0
  113. package/dist/plugins/linear/src/shared.js +2 -0
  114. package/dist/plugins/linear/src/states.js +2 -0
  115. package/dist/plugins/linear/src/teams.js +3 -0
  116. package/dist/plugins/linear/src/users.js +2 -0
  117. package/dist/plugins/linear/src/views.js +4 -0
  118. package/dist/plugins/linear/src/webhooks.js +4 -0
  119. package/dist/plugins/lingvanex/src/index.js +1 -0
  120. package/dist/plugins/linkedin/src/index.js +1 -0
  121. package/dist/plugins/lonescale/src/index.js +4 -0
  122. package/dist/plugins/magento/src/index.js +15 -0
  123. package/dist/plugins/mailcheck/src/index.js +1 -0
  124. package/dist/plugins/mailchimp/src/index.js +14 -0
  125. package/dist/plugins/mailerlite/src/index.js +4 -0
  126. package/dist/plugins/mailgun/src/index.js +1 -0
  127. package/dist/plugins/mailjet/src/index.js +3 -0
  128. package/dist/plugins/mandrill/src/index.js +2 -0
  129. package/dist/plugins/marketstack/src/index.js +3 -0
  130. package/dist/plugins/matrix/src/index.js +10 -0
  131. package/dist/plugins/mattermost/src/index.js +19 -0
  132. package/dist/plugins/mautic/src/index.js +20 -0
  133. package/dist/plugins/medium/src/index.js +3 -0
  134. package/dist/plugins/messagebird/src/index.js +2 -0
  135. package/dist/plugins/metabase/src/index.js +10 -0
  136. package/dist/plugins/microsoftCalendar/src/index.js +2 -0
  137. package/dist/plugins/microsoftFiles/src/index.js +5 -0
  138. package/dist/plugins/microsoftMail/src/index.js +4 -0
  139. package/dist/plugins/misp/src/index.js +44 -0
  140. package/dist/plugins/mocean/src/index.js +2 -0
  141. package/dist/plugins/monday/src/index.js +18 -0
  142. package/dist/plugins/monicaCrm/src/index.js +5 -0
  143. package/dist/plugins/msg91/src/index.js +1 -0
  144. package/dist/plugins/nasa/src/index.js +7 -0
  145. package/dist/plugins/netlify/src/index.js +7 -0
  146. package/dist/plugins/netscalerAdc/src/index.js +3 -0
  147. package/dist/plugins/nextcloud/src/index.js +13 -0
  148. package/dist/plugins/nocodb/src/index.js +5 -0
  149. package/dist/plugins/node/src/index.js +38 -0
  150. package/dist/plugins/notion/src/index.js +14 -0
  151. package/dist/plugins/npm/src/index.js +5 -0
  152. package/dist/plugins/odoo/src/index.js +6 -0
  153. package/dist/plugins/okta/src/index.js +5 -0
  154. package/dist/plugins/oneSimpleApi/src/index.js +10 -0
  155. package/dist/plugins/onfleet/src/index.js +24 -0
  156. package/dist/plugins/openThesaurus/src/index.js +1 -0
  157. package/dist/plugins/openai/src/index.js +1 -0
  158. package/dist/plugins/openweathermap/src/index.js +2 -0
  159. package/dist/plugins/oura/src/index.js +2 -0
  160. package/dist/plugins/paddle/src/index.js +9 -0
  161. package/dist/plugins/pagerduty/src/index.js +9 -0
  162. package/dist/plugins/parallel/src/index.js +1 -0
  163. package/dist/plugins/paypal/src/index.js +4 -0
  164. package/dist/plugins/peekalink/src/index.js +2 -0
  165. package/dist/plugins/phantombuster/src/index.js +5 -0
  166. package/dist/plugins/philipsHue/src/index.js +4 -0
  167. package/dist/plugins/pipedrive/src/index.js +14 -0
  168. package/dist/plugins/plivo/src/index.js +3 -0
  169. package/dist/plugins/postbin/src/index.js +6 -0
  170. package/dist/plugins/posthog/src/index.js +5 -0
  171. package/dist/plugins/profitwell/src/index.js +2 -0
  172. package/dist/plugins/pushbullet/src/index.js +4 -0
  173. package/dist/plugins/pushcut/src/index.js +1 -0
  174. package/dist/plugins/pushover/src/index.js +1 -0
  175. package/dist/plugins/quickbase/src/index.js +8 -0
  176. package/dist/plugins/quickbooks/src/index.js +5 -0
  177. package/dist/plugins/quickchart/src/index.js +1 -0
  178. package/dist/plugins/raindrop/src/index.js +13 -0
  179. package/dist/plugins/recraft/src/index.js +1 -0
  180. package/dist/plugins/reddit/src/index.js +10 -0
  181. package/dist/plugins/replicate/src/index.js +1 -0
  182. package/dist/plugins/rocketchat/src/index.js +1 -0
  183. package/dist/plugins/rundeck/src/index.js +2 -0
  184. package/dist/plugins/salesforce/src/metadata.js +4 -0
  185. package/dist/plugins/salesforce/src/query.js +5 -0
  186. package/dist/plugins/salesforce/src/sobjects.js +12 -0
  187. package/dist/plugins/salesmate/src/index.js +5 -0
  188. package/dist/plugins/securityScorecard/src/index.js +14 -0
  189. package/dist/plugins/segment/src/index.js +4 -0
  190. package/dist/plugins/sendgrid/src/index.js +10 -0
  191. package/dist/plugins/sendy/src/index.js +6 -0
  192. package/dist/plugins/sentry/src/index.js +24 -0
  193. package/dist/plugins/servicenow/src/index.js +10 -0
  194. package/dist/plugins/shiftLabs/src/index.js +6 -0
  195. package/dist/plugins/shiftLabs/src/issues.js +4 -0
  196. package/dist/plugins/shiftLabs/src/pages.js +10 -0
  197. package/dist/plugins/shiftLabs/src/shared.js +2 -0
  198. package/dist/plugins/shiftLabs/src/transcription.js +203 -0
  199. package/dist/plugins/shopify/src/index.js +10 -0
  200. package/dist/plugins/signl4/src/index.js +2 -0
  201. package/dist/plugins/slack/src/index.js +38 -0
  202. package/dist/plugins/sms77/src/index.js +2 -0
  203. package/dist/plugins/splunk/src/index.js +16 -0
  204. package/dist/plugins/spotify/src/index.js +30 -0
  205. package/dist/plugins/stackby/src/index.js +4 -0
  206. package/dist/plugins/steel/src/browser.js +7 -0
  207. package/dist/plugins/steel/src/captchas.js +3 -0
  208. package/dist/plugins/steel/src/credentials.js +4 -0
  209. package/dist/plugins/steel/src/extensions.js +5 -0
  210. package/dist/plugins/steel/src/files.js +10 -0
  211. package/dist/plugins/steel/src/profiles.js +4 -0
  212. package/dist/plugins/steel/src/sessions.js +11 -0
  213. package/dist/plugins/storyblok/src/index.js +7 -0
  214. package/dist/plugins/strapi/src/index.js +5 -0
  215. package/dist/plugins/strava/src/index.js +6 -0
  216. package/dist/plugins/stripe/src/index.js +20 -0
  217. package/dist/plugins/supabase/src/index.js +5 -0
  218. package/dist/plugins/syncromsp/src/index.js +20 -0
  219. package/dist/plugins/tapfiliate/src/index.js +11 -0
  220. package/dist/plugins/telegram/src/index.js +21 -0
  221. package/dist/plugins/thehive/src/index.js +23 -0
  222. package/dist/plugins/thehiveProject/src/index.js +31 -0
  223. package/dist/plugins/todoist/src/index.js +31 -0
  224. package/dist/plugins/together/src/index.js +1 -0
  225. package/dist/plugins/travisci/src/index.js +5 -0
  226. package/dist/plugins/trello/src/index.js +37 -0
  227. package/dist/plugins/twake/src/index.js +1 -0
  228. package/dist/plugins/twilio/src/index.js +2 -0
  229. package/dist/plugins/twist/src/index.js +22 -0
  230. package/dist/plugins/twitter/src/index.js +8 -0
  231. package/dist/plugins/unleashedSoftware/src/index.js +3 -0
  232. package/dist/plugins/uplead/src/index.js +2 -0
  233. package/dist/plugins/uproc/src/index.js +1 -0
  234. package/dist/plugins/uptimerobot/src/index.js +22 -0
  235. package/dist/plugins/urlscanio/src/index.js +3 -0
  236. package/dist/plugins/vercel/src/account.js +1 -0
  237. package/dist/plugins/vercel/src/deployments.js +5 -0
  238. package/dist/plugins/vercel/src/env.js +4 -0
  239. package/dist/plugins/vercel/src/projects.js +2 -0
  240. package/dist/plugins/vercel/src/shared.js +1 -0
  241. package/dist/plugins/vero/src/index.js +6 -0
  242. package/dist/plugins/vonage/src/index.js +1 -0
  243. package/dist/plugins/wekan/src/index.js +24 -0
  244. package/dist/plugins/woocommerce/src/index.js +5 -0
  245. package/dist/plugins/wordpress/src/index.js +10 -0
  246. package/dist/plugins/xai/src/index.js +1 -0
  247. package/dist/plugins/xero/src/index.js +8 -0
  248. package/dist/plugins/yourls/src/index.js +3 -0
  249. package/dist/plugins/zammad/src/index.js +12 -0
  250. package/dist/plugins/zendesk/src/index.js +18 -0
  251. package/dist/plugins/zoho/src/index.js +6 -0
  252. package/dist/plugins/zoom/src/index.js +5 -0
  253. package/dist/plugins/zulip/src/index.js +15 -0
  254. package/dist/sdk.d.ts +2 -1
  255. package/dist/sdk.js +1 -0
  256. package/package.json +1 -1
@@ -20,7 +20,9 @@
20
20
  * `POST /v1/presentations/{id}:batchUpdate` endpoint.
21
21
  */
22
22
  import { writeFileSync } from "node:fs";
23
+ import * as t from "typebox";
23
24
  import { googleAccessToken } from "../../_shared/googleAuth.js";
25
+ import { Id, NonEmptyString, PositiveInteger, RawGoogleObject, StringArray, stringEnum, } from "../../_shared/googleSchemas.js";
24
26
  // ─── Auth ────────────────────────────────────────────────────────
25
27
  async function accessToken(ctx) {
26
28
  return googleAccessToken(ctx, "googleSlides", SCOPES);
@@ -48,7 +50,8 @@ async function slidesRequest(ctx, method, path, body, qs) {
48
50
  headers: { Authorization: `Bearer ${token}`, Accept: "application/json" },
49
51
  };
50
52
  if (body && Object.keys(body).length > 0) {
51
- init.headers["Content-Type"] = "application/json";
53
+ init.headers["Content-Type"] =
54
+ "application/json";
52
55
  init.body = JSON.stringify(body);
53
56
  }
54
57
  const res = await fetch(url.toString(), init);
@@ -109,35 +112,61 @@ export default function googleSlides(rl) {
109
112
  ],
110
113
  });
111
114
  rl.setConnectionSchema({
112
- clientId: { type: "string", required: false, env: "GOOGLE_SLIDES_CLIENT_ID" },
113
- clientSecret: { type: "string", required: false, env: "GOOGLE_SLIDES_CLIENT_SECRET" },
114
- refreshToken: { type: "string", required: false, env: "GOOGLE_SLIDES_REFRESH_TOKEN" },
115
- serviceAccountJson: { type: "string", required: false, env: "GOOGLE_SLIDES_SERVICE_ACCOUNT_JSON" },
116
- serviceAccountEmail: { type: "string", required: false, env: "GOOGLE_SLIDES_SERVICE_ACCOUNT_EMAIL" },
117
- serviceAccountPrivateKey: { type: "string", required: false, env: "GOOGLE_SLIDES_SERVICE_ACCOUNT_PRIVATE_KEY" },
118
- serviceAccountSubject: { type: "string", required: false, env: "GOOGLE_SLIDES_SERVICE_ACCOUNT_SUBJECT" },
115
+ clientId: {
116
+ type: "string",
117
+ required: false,
118
+ env: "GOOGLE_SLIDES_CLIENT_ID",
119
+ },
120
+ clientSecret: {
121
+ type: "string",
122
+ required: false,
123
+ env: "GOOGLE_SLIDES_CLIENT_SECRET",
124
+ },
125
+ refreshToken: {
126
+ type: "string",
127
+ required: false,
128
+ env: "GOOGLE_SLIDES_REFRESH_TOKEN",
129
+ },
130
+ serviceAccountJson: {
131
+ type: "string",
132
+ required: false,
133
+ env: "GOOGLE_SLIDES_SERVICE_ACCOUNT_JSON",
134
+ },
135
+ serviceAccountEmail: {
136
+ type: "string",
137
+ required: false,
138
+ env: "GOOGLE_SLIDES_SERVICE_ACCOUNT_EMAIL",
139
+ },
140
+ serviceAccountPrivateKey: {
141
+ type: "string",
142
+ required: false,
143
+ env: "GOOGLE_SLIDES_SERVICE_ACCOUNT_PRIVATE_KEY",
144
+ },
145
+ serviceAccountSubject: {
146
+ type: "string",
147
+ required: false,
148
+ env: "GOOGLE_SLIDES_SERVICE_ACCOUNT_SUBJECT",
149
+ },
119
150
  accessToken: { type: "string", required: false },
120
151
  accessTokenExpiresAt: { type: "number", required: false },
121
152
  });
122
153
  // ── Presentation ──────────────────────────────────────
123
154
  rl.registerAction("presentation.create", {
155
+ access: "write",
124
156
  description: "Create a new empty presentation",
125
- inputSchema: { title: { type: "string", required: true } },
157
+ inputSchema: t.Object({ title: NonEmptyString }, { additionalProperties: false }),
126
158
  async execute(input, ctx) {
127
159
  const p = (input ?? {});
128
160
  return slidesRequest(ctx, "POST", "/presentations", { title: p.title });
129
161
  },
130
162
  });
131
163
  rl.registerAction("presentation.get", {
164
+ access: "read",
132
165
  description: "Get a presentation. Accepts a bare ID or a docs.google.com/presentation URL.",
133
- inputSchema: {
134
- presentation: { type: "string", required: true },
135
- fields: {
136
- type: "string",
137
- required: false,
138
- description: "Fields projection (e.g. 'slides' to get slides only)",
139
- },
140
- },
166
+ inputSchema: t.Object({
167
+ presentation: Id,
168
+ fields: t.Optional(NonEmptyString),
169
+ }, { additionalProperties: false }),
141
170
  async execute(input, ctx) {
142
171
  const p = (input ?? {});
143
172
  const id = extractPresentationId(p.presentation);
@@ -148,11 +177,12 @@ export default function googleSlides(rl) {
148
177
  },
149
178
  });
150
179
  rl.registerAction("presentation.listSlides", {
180
+ access: "read",
151
181
  description: "List slides in a presentation",
152
- inputSchema: {
153
- presentation: { type: "string", required: true },
154
- limit: { type: "number", required: false, description: "Max number of slides to return" },
155
- },
182
+ inputSchema: t.Object({
183
+ presentation: Id,
184
+ limit: t.Optional(PositiveInteger),
185
+ }, { additionalProperties: false }),
156
186
  async execute(input, ctx) {
157
187
  const p = (input ?? {});
158
188
  const id = extractPresentationId(p.presentation);
@@ -164,20 +194,18 @@ export default function googleSlides(rl) {
164
194
  },
165
195
  });
166
196
  rl.registerAction("presentation.replaceText", {
197
+ access: "write",
167
198
  description: "Replace text in a presentation. Pass one or more {text, replaceText, matchCase?, pageObjectIds?} entries; each becomes a replaceAllText request in a single batchUpdate.",
168
- inputSchema: {
169
- presentation: { type: "string", required: true },
170
- replacements: {
171
- type: "array",
172
- required: true,
173
- description: "[{text, replaceText, matchCase?, pageObjectIds?}] — pageObjectIds limits the scope to specific slides",
174
- },
175
- revisionId: {
176
- type: "string",
177
- required: false,
178
- description: "If set, request fails unless the presentation's current revisionId matches",
179
- },
180
- },
199
+ inputSchema: t.Object({
200
+ presentation: Id,
201
+ replacements: t.Array(t.Object({
202
+ text: NonEmptyString,
203
+ replaceText: t.String(),
204
+ matchCase: t.Optional(t.Boolean()),
205
+ pageObjectIds: t.Optional(StringArray),
206
+ }, { additionalProperties: false }), { minItems: 1 }),
207
+ revisionId: t.Optional(Id),
208
+ }, { additionalProperties: false }),
181
209
  async execute(input, ctx) {
182
210
  const p = (input ?? {});
183
211
  const id = extractPresentationId(p.presentation);
@@ -203,16 +231,13 @@ export default function googleSlides(rl) {
203
231
  },
204
232
  });
205
233
  rl.registerAction("presentation.batchUpdate", {
234
+ access: "write",
206
235
  description: "Raw passthrough to presentations.batchUpdate — pass a full `requests` array for layout edits, shape inserts, transform updates, etc.",
207
- inputSchema: {
208
- presentation: { type: "string", required: true },
209
- requests: { type: "array", required: true },
210
- writeControl: {
211
- type: "object",
212
- required: false,
213
- description: "{requiredRevisionId}",
214
- },
215
- },
236
+ inputSchema: t.Object({
237
+ presentation: Id,
238
+ requests: t.Array(RawGoogleObject, { minItems: 1 }),
239
+ writeControl: t.Optional(t.Object({ requiredRevisionId: Id }, { additionalProperties: false })),
240
+ }, { additionalProperties: false }),
216
241
  async execute(input, ctx) {
217
242
  const p = (input ?? {});
218
243
  const id = extractPresentationId(p.presentation);
@@ -224,11 +249,12 @@ export default function googleSlides(rl) {
224
249
  });
225
250
  // ── Page (slide) ──────────────────────────────────────
226
251
  rl.registerAction("page.get", {
252
+ access: "read",
227
253
  description: "Get a single slide (page) by objectId",
228
- inputSchema: {
229
- presentation: { type: "string", required: true },
230
- pageObjectId: { type: "string", required: true },
231
- },
254
+ inputSchema: t.Object({
255
+ presentation: Id,
256
+ pageObjectId: Id,
257
+ }, { additionalProperties: false }),
232
258
  async execute(input, ctx) {
233
259
  const p = (input ?? {});
234
260
  const id = extractPresentationId(p.presentation);
@@ -236,31 +262,21 @@ export default function googleSlides(rl) {
236
262
  },
237
263
  });
238
264
  rl.registerAction("page.getThumbnail", {
265
+ access: "write",
239
266
  description: "Get a thumbnail for a slide. Returns Slides' response { contentUrl, width, height } by default; set `savePath` to also download the PNG to disk, or `download=true` to return base64.",
240
- inputSchema: {
241
- presentation: { type: "string", required: true },
242
- pageObjectId: { type: "string", required: true },
243
- mimeType: {
244
- type: "string",
245
- required: false,
246
- description: "PNG (default) — the only type Slides currently exposes",
247
- },
248
- thumbnailSize: {
249
- type: "string",
250
- required: false,
251
- description: "THUMBNAIL_SIZE_UNSPECIFIED (default) | LARGE | MEDIUM | SMALL",
252
- },
253
- savePath: {
254
- type: "string",
255
- required: false,
256
- description: "Write the PNG bytes to this filesystem path",
257
- },
258
- download: {
259
- type: "boolean",
260
- required: false,
261
- description: "If true (and no savePath), include base64 bytes in the response",
262
- },
263
- },
267
+ inputSchema: t.Object({
268
+ presentation: Id,
269
+ pageObjectId: Id,
270
+ mimeType: t.Optional(t.Literal("PNG")),
271
+ thumbnailSize: t.Optional(stringEnum([
272
+ "THUMBNAIL_SIZE_UNSPECIFIED",
273
+ "LARGE",
274
+ "MEDIUM",
275
+ "SMALL",
276
+ ])),
277
+ savePath: t.Optional(NonEmptyString),
278
+ download: t.Optional(t.Boolean()),
279
+ }, { additionalProperties: false }),
264
280
  async execute(input, ctx) {
265
281
  const p = (input ?? {});
266
282
  const id = extractPresentationId(p.presentation);
@@ -282,7 +298,11 @@ export default function googleSlides(rl) {
282
298
  writeFileSync(p.savePath, bytes);
283
299
  return { ...res, path: p.savePath, size: bytes.byteLength };
284
300
  }
285
- return { ...res, size: bytes.byteLength, contentBase64: bytes.toString("base64") };
301
+ return {
302
+ ...res,
303
+ size: bytes.byteLength,
304
+ contentBase64: bytes.toString("base64"),
305
+ };
286
306
  },
287
307
  });
288
308
  }
@@ -19,7 +19,9 @@
19
19
  * Google's Tasks API is strict about RFC3339 with a timezone — we
20
20
  * normalize ISO input via `Date.toISOString()` when detected.
21
21
  */
22
+ import * as t from "typebox";
22
23
  import { googleAccessToken } from "../../_shared/googleAuth.js";
24
+ import { GoogleTimestamp, Id, stringEnum, } from "../../_shared/googleSchemas.js";
23
25
  // ─── Auth ────────────────────────────────────────────────────────
24
26
  async function accessToken(ctx) {
25
27
  return googleAccessToken(ctx, "googleTasks", SCOPES);
@@ -86,12 +88,12 @@ function toRFC3339(v) {
86
88
  if (typeof v === "number") {
87
89
  return new Date(v).toISOString();
88
90
  }
89
- if (v instanceof Date)
90
- return v.toISOString();
91
- throw new Error("googleTasks: date must be ISO string, epoch ms, or Date");
91
+ throw new Error("googleTasks: date must be an ISO string or epoch milliseconds");
92
92
  }
93
93
  // ─── Plugin ──────────────────────────────────────────────────────
94
94
  const SCOPES = ["https://www.googleapis.com/auth/tasks"];
95
+ const taskStatusSchema = stringEnum(["needsAction", "completed"]);
96
+ const pageSizeSchema = t.Integer({ minimum: 1, maximum: 100 });
95
97
  export default function googleTasks(rl) {
96
98
  rl.setName("googleTasks");
97
99
  rl.setVersion("0.1.0");
@@ -139,12 +141,13 @@ export default function googleTasks(rl) {
139
141
  });
140
142
  // ── Task lists ────────────────────────────────────────
141
143
  rl.registerAction("taskList.list", {
144
+ access: "read",
142
145
  description: "List the authenticated user's task lists",
143
- inputSchema: {
144
- returnAll: { type: "boolean", required: false },
145
- maxResults: { type: "number", required: false },
146
- pageToken: { type: "string", required: false },
147
- },
146
+ inputSchema: t.Object({
147
+ returnAll: t.Optional(t.Boolean()),
148
+ maxResults: t.Optional(pageSizeSchema),
149
+ pageToken: t.Optional(Id),
150
+ }, { additionalProperties: false }),
148
151
  async execute(input, ctx) {
149
152
  const p = (input ?? {});
150
153
  const qs = {};
@@ -159,27 +162,30 @@ export default function googleTasks(rl) {
159
162
  },
160
163
  });
161
164
  rl.registerAction("taskList.get", {
165
+ access: "read",
162
166
  description: "Get a task list by ID",
163
- inputSchema: { taskListId: { type: "string", required: true } },
167
+ inputSchema: t.Object({ taskListId: Id }, { additionalProperties: false }),
164
168
  async execute(input, ctx) {
165
169
  const p = (input ?? {});
166
170
  return tasksRequest(ctx, "GET", `/users/@me/lists/${p.taskListId}`);
167
171
  },
168
172
  });
169
173
  rl.registerAction("taskList.create", {
174
+ access: "write",
170
175
  description: "Create a new task list",
171
- inputSchema: { title: { type: "string", required: true } },
176
+ inputSchema: t.Object({ title: t.String() }, { additionalProperties: false }),
172
177
  async execute(input, ctx) {
173
178
  const p = (input ?? {});
174
179
  return tasksRequest(ctx, "POST", "/users/@me/lists", { title: p.title });
175
180
  },
176
181
  });
177
182
  rl.registerAction("taskList.update", {
183
+ access: "write",
178
184
  description: "Update a task list (currently only `title` is writable).",
179
- inputSchema: {
180
- taskListId: { type: "string", required: true },
181
- title: { type: "string", required: true },
182
- },
185
+ inputSchema: t.Object({
186
+ taskListId: Id,
187
+ title: t.String(),
188
+ }, { additionalProperties: false }),
183
189
  async execute(input, ctx) {
184
190
  const p = (input ?? {});
185
191
  return tasksRequest(ctx, "PATCH", `/users/@me/lists/${p.taskListId}`, {
@@ -188,8 +194,9 @@ export default function googleTasks(rl) {
188
194
  },
189
195
  });
190
196
  rl.registerAction("taskList.delete", {
197
+ access: "write",
191
198
  description: "Delete a task list and all its tasks",
192
- inputSchema: { taskListId: { type: "string", required: true } },
199
+ inputSchema: t.Object({ taskListId: Id }, { additionalProperties: false }),
193
200
  async execute(input, ctx) {
194
201
  const p = (input ?? {});
195
202
  await tasksRequest(ctx, "DELETE", `/users/@me/lists/${p.taskListId}`);
@@ -198,38 +205,25 @@ export default function googleTasks(rl) {
198
205
  });
199
206
  // ── Tasks ─────────────────────────────────────────────
200
207
  rl.registerAction("task.create", {
208
+ access: "write",
201
209
  description: "Create a task in a list",
202
- inputSchema: {
203
- taskListId: { type: "string", required: true },
204
- title: { type: "string", required: true },
205
- notes: { type: "string", required: false },
206
- due: {
207
- type: "string",
208
- required: false,
209
- description: "RFC3339 or ISO datetime; normalized to RFC3339",
210
- },
211
- status: {
212
- type: "string",
213
- required: false,
214
- description: "needsAction (default) | completed",
215
- },
216
- completed: {
217
- type: "string",
218
- required: false,
219
- description: "Completion timestamp; implies status=completed",
220
- },
221
- deleted: { type: "boolean", required: false },
222
- parent: {
223
- type: "string",
224
- required: false,
210
+ inputSchema: t.Object({
211
+ taskListId: Id,
212
+ title: t.String(),
213
+ notes: t.Optional(t.String()),
214
+ due: t.Optional(GoogleTimestamp),
215
+ status: t.Optional(taskStatusSchema),
216
+ completed: t.Optional(GoogleTimestamp),
217
+ deleted: t.Optional(t.Boolean()),
218
+ parent: t.Optional(t.String({
219
+ minLength: 1,
225
220
  description: "Parent task ID (nests this task under another)",
226
- },
227
- previous: {
228
- type: "string",
229
- required: false,
221
+ })),
222
+ previous: t.Optional(t.String({
223
+ minLength: 1,
230
224
  description: "Insert after this task ID; omit to place at top of level",
231
- },
232
- },
225
+ })),
226
+ }, { additionalProperties: false }),
233
227
  async execute(input, ctx) {
234
228
  const p = (input ?? {});
235
229
  const body = { title: p.title };
@@ -254,32 +248,34 @@ export default function googleTasks(rl) {
254
248
  },
255
249
  });
256
250
  rl.registerAction("task.get", {
251
+ access: "read",
257
252
  description: "Get a single task",
258
- inputSchema: {
259
- taskListId: { type: "string", required: true },
260
- taskId: { type: "string", required: true },
261
- },
253
+ inputSchema: t.Object({
254
+ taskListId: Id,
255
+ taskId: Id,
256
+ }, { additionalProperties: false }),
262
257
  async execute(input, ctx) {
263
258
  const p = (input ?? {});
264
259
  return tasksRequest(ctx, "GET", `/lists/${p.taskListId}/tasks/${p.taskId}`);
265
260
  },
266
261
  });
267
262
  rl.registerAction("task.list", {
263
+ access: "read",
268
264
  description: "List tasks in a list. Filters: dueMin/dueMax, completedMin/completedMax, updatedMin, showCompleted/showDeleted/showHidden.",
269
- inputSchema: {
270
- taskListId: { type: "string", required: true },
271
- showCompleted: { type: "boolean", required: false, description: "default: true" },
272
- showDeleted: { type: "boolean", required: false },
273
- showHidden: { type: "boolean", required: false },
274
- dueMin: { type: "string", required: false },
275
- dueMax: { type: "string", required: false },
276
- completedMin: { type: "string", required: false },
277
- completedMax: { type: "string", required: false },
278
- updatedMin: { type: "string", required: false },
279
- returnAll: { type: "boolean", required: false },
280
- maxResults: { type: "number", required: false },
281
- pageToken: { type: "string", required: false },
282
- },
265
+ inputSchema: t.Object({
266
+ taskListId: Id,
267
+ showCompleted: t.Optional(t.Boolean({ description: "Include completed tasks (default: true)" })),
268
+ showDeleted: t.Optional(t.Boolean()),
269
+ showHidden: t.Optional(t.Boolean()),
270
+ dueMin: t.Optional(GoogleTimestamp),
271
+ dueMax: t.Optional(GoogleTimestamp),
272
+ completedMin: t.Optional(GoogleTimestamp),
273
+ completedMax: t.Optional(GoogleTimestamp),
274
+ updatedMin: t.Optional(GoogleTimestamp),
275
+ returnAll: t.Optional(t.Boolean()),
276
+ maxResults: t.Optional(pageSizeSchema),
277
+ pageToken: t.Optional(Id),
278
+ }, { additionalProperties: false }),
283
279
  async execute(input, ctx) {
284
280
  const p = (input ?? {});
285
281
  const qs = {
@@ -304,22 +300,28 @@ export default function googleTasks(rl) {
304
300
  },
305
301
  });
306
302
  rl.registerAction("task.update", {
303
+ access: "write",
307
304
  description: "Patch a task. Only supplied fields are sent. Set status=completed (and optionally `completed` timestamp) to mark done.",
308
- inputSchema: {
309
- taskListId: { type: "string", required: true },
310
- taskId: { type: "string", required: true },
311
- title: { type: "string", required: false },
312
- notes: { type: "string", required: false },
313
- due: { type: "string", required: false },
314
- status: { type: "string", required: false },
315
- completed: { type: "string", required: false },
316
- deleted: { type: "boolean", required: false },
317
- previous: {
318
- type: "string",
319
- required: false,
320
- description: "Reorder: place after this task ID (query-only, not in body)",
321
- },
322
- },
305
+ inputSchema: t.Object({
306
+ taskListId: Id,
307
+ taskId: Id,
308
+ title: t.Optional(t.String()),
309
+ notes: t.Optional(t.String()),
310
+ due: t.Optional(GoogleTimestamp),
311
+ status: t.Optional(taskStatusSchema),
312
+ completed: t.Optional(GoogleTimestamp),
313
+ deleted: t.Optional(t.Boolean()),
314
+ }, {
315
+ additionalProperties: false,
316
+ anyOf: [
317
+ { required: ["title"] },
318
+ { required: ["notes"] },
319
+ { required: ["due"] },
320
+ { required: ["status"] },
321
+ { required: ["completed"] },
322
+ { required: ["deleted"] },
323
+ ],
324
+ }),
323
325
  async execute(input, ctx) {
324
326
  const p = (input ?? {});
325
327
  const body = {};
@@ -340,18 +342,16 @@ export default function googleTasks(rl) {
340
342
  if (Object.keys(body).length === 0) {
341
343
  throw new Error("googleTasks: nothing to update");
342
344
  }
343
- const qs = {};
344
- if (p.previous)
345
- qs.previous = p.previous;
346
- return tasksRequest(ctx, "PATCH", `/lists/${p.taskListId}/tasks/${p.taskId}`, body, qs);
345
+ return tasksRequest(ctx, "PATCH", `/lists/${p.taskListId}/tasks/${p.taskId}`, body);
347
346
  },
348
347
  });
349
348
  rl.registerAction("task.delete", {
349
+ access: "write",
350
350
  description: "Delete a task",
351
- inputSchema: {
352
- taskListId: { type: "string", required: true },
353
- taskId: { type: "string", required: true },
354
- },
351
+ inputSchema: t.Object({
352
+ taskListId: Id,
353
+ taskId: Id,
354
+ }, { additionalProperties: false }),
355
355
  async execute(input, ctx) {
356
356
  const p = (input ?? {});
357
357
  await tasksRequest(ctx, "DELETE", `/lists/${p.taskListId}/tasks/${p.taskId}`);
@@ -359,13 +359,14 @@ export default function googleTasks(rl) {
359
359
  },
360
360
  });
361
361
  rl.registerAction("task.move", {
362
+ access: "write",
362
363
  description: "Move a task within its list (reorder or reparent). `parent` nests under another task; `previous` places it after a sibling.",
363
- inputSchema: {
364
- taskListId: { type: "string", required: true },
365
- taskId: { type: "string", required: true },
366
- parent: { type: "string", required: false },
367
- previous: { type: "string", required: false },
368
- },
364
+ inputSchema: t.Object({
365
+ taskListId: Id,
366
+ taskId: Id,
367
+ parent: t.Optional(Id),
368
+ previous: t.Optional(Id),
369
+ }, { additionalProperties: false }),
369
370
  async execute(input, ctx) {
370
371
  const p = (input ?? {});
371
372
  const qs = {};
@@ -377,8 +378,9 @@ export default function googleTasks(rl) {
377
378
  },
378
379
  });
379
380
  rl.registerAction("task.clear", {
381
+ access: "write",
380
382
  description: "Hide all completed tasks in a list from the default view. They remain accessible via task.list with showHidden=true.",
381
- inputSchema: { taskListId: { type: "string", required: true } },
383
+ inputSchema: t.Object({ taskListId: Id }, { additionalProperties: false }),
382
384
  async execute(input, ctx) {
383
385
  const p = (input ?? {});
384
386
  await tasksRequest(ctx, "POST", `/lists/${p.taskListId}/clear`);
@@ -51,6 +51,7 @@ export default function gotify(rl) {
51
51
  },
52
52
  });
53
53
  rl.registerAction("message.create", {
54
+ access: "write",
54
55
  description: "Send a push message",
55
56
  inputSchema: {
56
57
  message: { type: "string", required: true, description: "Message text" },
@@ -81,6 +82,7 @@ export default function gotify(rl) {
81
82
  },
82
83
  });
83
84
  rl.registerAction("message.delete", {
85
+ access: "write",
84
86
  description: "Delete a message",
85
87
  inputSchema: {
86
88
  messageId: { type: "string", required: true, description: "Message ID" },
@@ -93,6 +95,7 @@ export default function gotify(rl) {
93
95
  },
94
96
  });
95
97
  rl.registerAction("message.list", {
98
+ access: "read",
96
99
  description: "List messages",
97
100
  inputSchema: {
98
101
  limit: { type: "number", required: false, description: "Max results" },