runline 0.12.0 → 0.14.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.
- package/dist/plugins/_shared/googleSchemas.js +23 -0
- package/dist/plugins/gmail/src/index.js +168 -184
- package/dist/plugins/googleAppsScript/src/index.js +88 -43
- package/dist/plugins/googleCalendar/src/index.js +307 -250
- package/dist/plugins/googleContacts/src/index.js +134 -145
- package/dist/plugins/googleDocs/src/documents.js +27 -38
- package/dist/plugins/googleDocs/src/formatting.js +49 -47
- package/dist/plugins/googleDocs/src/images.js +21 -26
- package/dist/plugins/googleDocs/src/shared.js +55 -0
- package/dist/plugins/googleDocs/src/structure.js +98 -123
- package/dist/plugins/googleDocs/src/tables.js +92 -154
- package/dist/plugins/googleDocs/src/tabs.js +24 -23
- package/dist/plugins/googleDocs/src/text.js +97 -136
- package/dist/plugins/googleDrive/src/index.js +414 -408
- package/dist/plugins/googleImage/src/index.js +13 -16
- package/dist/plugins/googleSheets/src/index.js +504 -339
- package/dist/plugins/googleSlides/src/index.js +85 -72
- package/dist/plugins/googleTasks/src/index.js +82 -92
- package/dist/plugins/shiftLabs/src/index.js +10 -0
- package/dist/plugins/shiftLabs/src/issue-views.js +179 -0
- package/dist/plugins/shiftLabs/src/issues.js +153 -35
- package/dist/plugins/shiftLabs/src/projects.js +93 -0
- package/dist/plugins/shiftLabs/src/shared.js +26 -11
- package/dist/plugins/shiftLabs/src/transcription.js +203 -0
- 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"] =
|
|
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,13 +112,41 @@ export default function googleSlides(rl) {
|
|
|
109
112
|
],
|
|
110
113
|
});
|
|
111
114
|
rl.setConnectionSchema({
|
|
112
|
-
clientId: {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
});
|
|
@@ -123,7 +154,7 @@ export default function googleSlides(rl) {
|
|
|
123
154
|
rl.registerAction("presentation.create", {
|
|
124
155
|
access: "write",
|
|
125
156
|
description: "Create a new empty presentation",
|
|
126
|
-
inputSchema: { title:
|
|
157
|
+
inputSchema: t.Object({ title: NonEmptyString }, { additionalProperties: false }),
|
|
127
158
|
async execute(input, ctx) {
|
|
128
159
|
const p = (input ?? {});
|
|
129
160
|
return slidesRequest(ctx, "POST", "/presentations", { title: p.title });
|
|
@@ -132,14 +163,10 @@ export default function googleSlides(rl) {
|
|
|
132
163
|
rl.registerAction("presentation.get", {
|
|
133
164
|
access: "read",
|
|
134
165
|
description: "Get a presentation. Accepts a bare ID or a docs.google.com/presentation URL.",
|
|
135
|
-
inputSchema: {
|
|
136
|
-
presentation:
|
|
137
|
-
fields:
|
|
138
|
-
|
|
139
|
-
required: false,
|
|
140
|
-
description: "Fields projection (e.g. 'slides' to get slides only)",
|
|
141
|
-
},
|
|
142
|
-
},
|
|
166
|
+
inputSchema: t.Object({
|
|
167
|
+
presentation: Id,
|
|
168
|
+
fields: t.Optional(NonEmptyString),
|
|
169
|
+
}, { additionalProperties: false }),
|
|
143
170
|
async execute(input, ctx) {
|
|
144
171
|
const p = (input ?? {});
|
|
145
172
|
const id = extractPresentationId(p.presentation);
|
|
@@ -152,10 +179,10 @@ export default function googleSlides(rl) {
|
|
|
152
179
|
rl.registerAction("presentation.listSlides", {
|
|
153
180
|
access: "read",
|
|
154
181
|
description: "List slides in a presentation",
|
|
155
|
-
inputSchema: {
|
|
156
|
-
presentation:
|
|
157
|
-
limit:
|
|
158
|
-
},
|
|
182
|
+
inputSchema: t.Object({
|
|
183
|
+
presentation: Id,
|
|
184
|
+
limit: t.Optional(PositiveInteger),
|
|
185
|
+
}, { additionalProperties: false }),
|
|
159
186
|
async execute(input, ctx) {
|
|
160
187
|
const p = (input ?? {});
|
|
161
188
|
const id = extractPresentationId(p.presentation);
|
|
@@ -169,19 +196,16 @@ export default function googleSlides(rl) {
|
|
|
169
196
|
rl.registerAction("presentation.replaceText", {
|
|
170
197
|
access: "write",
|
|
171
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.",
|
|
172
|
-
inputSchema: {
|
|
173
|
-
presentation:
|
|
174
|
-
replacements: {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
description: "If set, request fails unless the presentation's current revisionId matches",
|
|
183
|
-
},
|
|
184
|
-
},
|
|
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 }),
|
|
185
209
|
async execute(input, ctx) {
|
|
186
210
|
const p = (input ?? {});
|
|
187
211
|
const id = extractPresentationId(p.presentation);
|
|
@@ -209,15 +233,11 @@ export default function googleSlides(rl) {
|
|
|
209
233
|
rl.registerAction("presentation.batchUpdate", {
|
|
210
234
|
access: "write",
|
|
211
235
|
description: "Raw passthrough to presentations.batchUpdate — pass a full `requests` array for layout edits, shape inserts, transform updates, etc.",
|
|
212
|
-
inputSchema: {
|
|
213
|
-
presentation:
|
|
214
|
-
requests: {
|
|
215
|
-
writeControl: {
|
|
216
|
-
|
|
217
|
-
required: false,
|
|
218
|
-
description: "{requiredRevisionId}",
|
|
219
|
-
},
|
|
220
|
-
},
|
|
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 }),
|
|
221
241
|
async execute(input, ctx) {
|
|
222
242
|
const p = (input ?? {});
|
|
223
243
|
const id = extractPresentationId(p.presentation);
|
|
@@ -231,10 +251,10 @@ export default function googleSlides(rl) {
|
|
|
231
251
|
rl.registerAction("page.get", {
|
|
232
252
|
access: "read",
|
|
233
253
|
description: "Get a single slide (page) by objectId",
|
|
234
|
-
inputSchema: {
|
|
235
|
-
presentation:
|
|
236
|
-
pageObjectId:
|
|
237
|
-
},
|
|
254
|
+
inputSchema: t.Object({
|
|
255
|
+
presentation: Id,
|
|
256
|
+
pageObjectId: Id,
|
|
257
|
+
}, { additionalProperties: false }),
|
|
238
258
|
async execute(input, ctx) {
|
|
239
259
|
const p = (input ?? {});
|
|
240
260
|
const id = extractPresentationId(p.presentation);
|
|
@@ -244,30 +264,19 @@ export default function googleSlides(rl) {
|
|
|
244
264
|
rl.registerAction("page.getThumbnail", {
|
|
245
265
|
access: "write",
|
|
246
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.",
|
|
247
|
-
inputSchema: {
|
|
248
|
-
presentation:
|
|
249
|
-
pageObjectId:
|
|
250
|
-
mimeType:
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
savePath: {
|
|
261
|
-
type: "string",
|
|
262
|
-
required: false,
|
|
263
|
-
description: "Write the PNG bytes to this filesystem path",
|
|
264
|
-
},
|
|
265
|
-
download: {
|
|
266
|
-
type: "boolean",
|
|
267
|
-
required: false,
|
|
268
|
-
description: "If true (and no savePath), include base64 bytes in the response",
|
|
269
|
-
},
|
|
270
|
-
},
|
|
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 }),
|
|
271
280
|
async execute(input, ctx) {
|
|
272
281
|
const p = (input ?? {});
|
|
273
282
|
const id = extractPresentationId(p.presentation);
|
|
@@ -289,7 +298,11 @@ export default function googleSlides(rl) {
|
|
|
289
298
|
writeFileSync(p.savePath, bytes);
|
|
290
299
|
return { ...res, path: p.savePath, size: bytes.byteLength };
|
|
291
300
|
}
|
|
292
|
-
return {
|
|
301
|
+
return {
|
|
302
|
+
...res,
|
|
303
|
+
size: bytes.byteLength,
|
|
304
|
+
contentBase64: bytes.toString("base64"),
|
|
305
|
+
};
|
|
293
306
|
},
|
|
294
307
|
});
|
|
295
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
|
-
|
|
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");
|
|
@@ -141,11 +143,11 @@ export default function googleTasks(rl) {
|
|
|
141
143
|
rl.registerAction("taskList.list", {
|
|
142
144
|
access: "read",
|
|
143
145
|
description: "List the authenticated user's task lists",
|
|
144
|
-
inputSchema: {
|
|
145
|
-
returnAll:
|
|
146
|
-
maxResults:
|
|
147
|
-
pageToken:
|
|
148
|
-
},
|
|
146
|
+
inputSchema: t.Object({
|
|
147
|
+
returnAll: t.Optional(t.Boolean()),
|
|
148
|
+
maxResults: t.Optional(pageSizeSchema),
|
|
149
|
+
pageToken: t.Optional(Id),
|
|
150
|
+
}, { additionalProperties: false }),
|
|
149
151
|
async execute(input, ctx) {
|
|
150
152
|
const p = (input ?? {});
|
|
151
153
|
const qs = {};
|
|
@@ -162,7 +164,7 @@ export default function googleTasks(rl) {
|
|
|
162
164
|
rl.registerAction("taskList.get", {
|
|
163
165
|
access: "read",
|
|
164
166
|
description: "Get a task list by ID",
|
|
165
|
-
inputSchema: { taskListId:
|
|
167
|
+
inputSchema: t.Object({ taskListId: Id }, { additionalProperties: false }),
|
|
166
168
|
async execute(input, ctx) {
|
|
167
169
|
const p = (input ?? {});
|
|
168
170
|
return tasksRequest(ctx, "GET", `/users/@me/lists/${p.taskListId}`);
|
|
@@ -171,7 +173,7 @@ export default function googleTasks(rl) {
|
|
|
171
173
|
rl.registerAction("taskList.create", {
|
|
172
174
|
access: "write",
|
|
173
175
|
description: "Create a new task list",
|
|
174
|
-
inputSchema: { title:
|
|
176
|
+
inputSchema: t.Object({ title: t.String() }, { additionalProperties: false }),
|
|
175
177
|
async execute(input, ctx) {
|
|
176
178
|
const p = (input ?? {});
|
|
177
179
|
return tasksRequest(ctx, "POST", "/users/@me/lists", { title: p.title });
|
|
@@ -180,10 +182,10 @@ export default function googleTasks(rl) {
|
|
|
180
182
|
rl.registerAction("taskList.update", {
|
|
181
183
|
access: "write",
|
|
182
184
|
description: "Update a task list (currently only `title` is writable).",
|
|
183
|
-
inputSchema: {
|
|
184
|
-
taskListId:
|
|
185
|
-
title:
|
|
186
|
-
},
|
|
185
|
+
inputSchema: t.Object({
|
|
186
|
+
taskListId: Id,
|
|
187
|
+
title: t.String(),
|
|
188
|
+
}, { additionalProperties: false }),
|
|
187
189
|
async execute(input, ctx) {
|
|
188
190
|
const p = (input ?? {});
|
|
189
191
|
return tasksRequest(ctx, "PATCH", `/users/@me/lists/${p.taskListId}`, {
|
|
@@ -194,7 +196,7 @@ export default function googleTasks(rl) {
|
|
|
194
196
|
rl.registerAction("taskList.delete", {
|
|
195
197
|
access: "write",
|
|
196
198
|
description: "Delete a task list and all its tasks",
|
|
197
|
-
inputSchema: { taskListId:
|
|
199
|
+
inputSchema: t.Object({ taskListId: Id }, { additionalProperties: false }),
|
|
198
200
|
async execute(input, ctx) {
|
|
199
201
|
const p = (input ?? {});
|
|
200
202
|
await tasksRequest(ctx, "DELETE", `/users/@me/lists/${p.taskListId}`);
|
|
@@ -205,37 +207,23 @@ export default function googleTasks(rl) {
|
|
|
205
207
|
rl.registerAction("task.create", {
|
|
206
208
|
access: "write",
|
|
207
209
|
description: "Create a task in a list",
|
|
208
|
-
inputSchema: {
|
|
209
|
-
taskListId:
|
|
210
|
-
title:
|
|
211
|
-
notes:
|
|
212
|
-
due:
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
type: "string",
|
|
219
|
-
required: false,
|
|
220
|
-
description: "needsAction (default) | completed",
|
|
221
|
-
},
|
|
222
|
-
completed: {
|
|
223
|
-
type: "string",
|
|
224
|
-
required: false,
|
|
225
|
-
description: "Completion timestamp; implies status=completed",
|
|
226
|
-
},
|
|
227
|
-
deleted: { type: "boolean", required: false },
|
|
228
|
-
parent: {
|
|
229
|
-
type: "string",
|
|
230
|
-
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,
|
|
231
220
|
description: "Parent task ID (nests this task under another)",
|
|
232
|
-
},
|
|
233
|
-
previous: {
|
|
234
|
-
|
|
235
|
-
required: false,
|
|
221
|
+
})),
|
|
222
|
+
previous: t.Optional(t.String({
|
|
223
|
+
minLength: 1,
|
|
236
224
|
description: "Insert after this task ID; omit to place at top of level",
|
|
237
|
-
},
|
|
238
|
-
},
|
|
225
|
+
})),
|
|
226
|
+
}, { additionalProperties: false }),
|
|
239
227
|
async execute(input, ctx) {
|
|
240
228
|
const p = (input ?? {});
|
|
241
229
|
const body = { title: p.title };
|
|
@@ -262,10 +250,10 @@ export default function googleTasks(rl) {
|
|
|
262
250
|
rl.registerAction("task.get", {
|
|
263
251
|
access: "read",
|
|
264
252
|
description: "Get a single task",
|
|
265
|
-
inputSchema: {
|
|
266
|
-
taskListId:
|
|
267
|
-
taskId:
|
|
268
|
-
},
|
|
253
|
+
inputSchema: t.Object({
|
|
254
|
+
taskListId: Id,
|
|
255
|
+
taskId: Id,
|
|
256
|
+
}, { additionalProperties: false }),
|
|
269
257
|
async execute(input, ctx) {
|
|
270
258
|
const p = (input ?? {});
|
|
271
259
|
return tasksRequest(ctx, "GET", `/lists/${p.taskListId}/tasks/${p.taskId}`);
|
|
@@ -274,20 +262,20 @@ export default function googleTasks(rl) {
|
|
|
274
262
|
rl.registerAction("task.list", {
|
|
275
263
|
access: "read",
|
|
276
264
|
description: "List tasks in a list. Filters: dueMin/dueMax, completedMin/completedMax, updatedMin, showCompleted/showDeleted/showHidden.",
|
|
277
|
-
inputSchema: {
|
|
278
|
-
taskListId:
|
|
279
|
-
showCompleted: {
|
|
280
|
-
showDeleted:
|
|
281
|
-
showHidden:
|
|
282
|
-
dueMin:
|
|
283
|
-
dueMax:
|
|
284
|
-
completedMin:
|
|
285
|
-
completedMax:
|
|
286
|
-
updatedMin:
|
|
287
|
-
returnAll:
|
|
288
|
-
maxResults:
|
|
289
|
-
pageToken:
|
|
290
|
-
},
|
|
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 }),
|
|
291
279
|
async execute(input, ctx) {
|
|
292
280
|
const p = (input ?? {});
|
|
293
281
|
const qs = {
|
|
@@ -314,21 +302,26 @@ export default function googleTasks(rl) {
|
|
|
314
302
|
rl.registerAction("task.update", {
|
|
315
303
|
access: "write",
|
|
316
304
|
description: "Patch a task. Only supplied fields are sent. Set status=completed (and optionally `completed` timestamp) to mark done.",
|
|
317
|
-
inputSchema: {
|
|
318
|
-
taskListId:
|
|
319
|
-
taskId:
|
|
320
|
-
title:
|
|
321
|
-
notes:
|
|
322
|
-
due:
|
|
323
|
-
status:
|
|
324
|
-
completed:
|
|
325
|
-
deleted:
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
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
|
+
}),
|
|
332
325
|
async execute(input, ctx) {
|
|
333
326
|
const p = (input ?? {});
|
|
334
327
|
const body = {};
|
|
@@ -349,19 +342,16 @@ export default function googleTasks(rl) {
|
|
|
349
342
|
if (Object.keys(body).length === 0) {
|
|
350
343
|
throw new Error("googleTasks: nothing to update");
|
|
351
344
|
}
|
|
352
|
-
|
|
353
|
-
if (p.previous)
|
|
354
|
-
qs.previous = p.previous;
|
|
355
|
-
return tasksRequest(ctx, "PATCH", `/lists/${p.taskListId}/tasks/${p.taskId}`, body, qs);
|
|
345
|
+
return tasksRequest(ctx, "PATCH", `/lists/${p.taskListId}/tasks/${p.taskId}`, body);
|
|
356
346
|
},
|
|
357
347
|
});
|
|
358
348
|
rl.registerAction("task.delete", {
|
|
359
349
|
access: "write",
|
|
360
350
|
description: "Delete a task",
|
|
361
|
-
inputSchema: {
|
|
362
|
-
taskListId:
|
|
363
|
-
taskId:
|
|
364
|
-
},
|
|
351
|
+
inputSchema: t.Object({
|
|
352
|
+
taskListId: Id,
|
|
353
|
+
taskId: Id,
|
|
354
|
+
}, { additionalProperties: false }),
|
|
365
355
|
async execute(input, ctx) {
|
|
366
356
|
const p = (input ?? {});
|
|
367
357
|
await tasksRequest(ctx, "DELETE", `/lists/${p.taskListId}/tasks/${p.taskId}`);
|
|
@@ -371,12 +361,12 @@ export default function googleTasks(rl) {
|
|
|
371
361
|
rl.registerAction("task.move", {
|
|
372
362
|
access: "write",
|
|
373
363
|
description: "Move a task within its list (reorder or reparent). `parent` nests under another task; `previous` places it after a sibling.",
|
|
374
|
-
inputSchema: {
|
|
375
|
-
taskListId:
|
|
376
|
-
taskId:
|
|
377
|
-
parent:
|
|
378
|
-
previous:
|
|
379
|
-
},
|
|
364
|
+
inputSchema: t.Object({
|
|
365
|
+
taskListId: Id,
|
|
366
|
+
taskId: Id,
|
|
367
|
+
parent: t.Optional(Id),
|
|
368
|
+
previous: t.Optional(Id),
|
|
369
|
+
}, { additionalProperties: false }),
|
|
380
370
|
async execute(input, ctx) {
|
|
381
371
|
const p = (input ?? {});
|
|
382
372
|
const qs = {};
|
|
@@ -390,7 +380,7 @@ export default function googleTasks(rl) {
|
|
|
390
380
|
rl.registerAction("task.clear", {
|
|
391
381
|
access: "write",
|
|
392
382
|
description: "Hide all completed tasks in a list from the default view. They remain accessible via task.list with showHidden=true.",
|
|
393
|
-
inputSchema: { taskListId:
|
|
383
|
+
inputSchema: t.Object({ taskListId: Id }, { additionalProperties: false }),
|
|
394
384
|
async execute(input, ctx) {
|
|
395
385
|
const p = (input ?? {});
|
|
396
386
|
await tasksRequest(ctx, "POST", `/lists/${p.taskListId}/clear`);
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import * as t from "typebox";
|
|
2
|
+
import { registerIssueViewActions } from "./issue-views.js";
|
|
2
3
|
import { registerIssueActions } from "./issues.js";
|
|
3
4
|
import { registerPageActions } from "./pages.js";
|
|
5
|
+
import { registerProjectActions } from "./projects.js";
|
|
6
|
+
import { registerTranscriptionActions } from "./transcription.js";
|
|
4
7
|
export default function shiftLabs(rl) {
|
|
5
8
|
rl.setName("shiftLabs");
|
|
6
9
|
rl.setVersion("0.1.0");
|
|
@@ -9,7 +12,14 @@ export default function shiftLabs(rl) {
|
|
|
9
12
|
description: "Shift Labs API key",
|
|
10
13
|
env: "SHIFT_LABS_API_KEY",
|
|
11
14
|
}),
|
|
15
|
+
organizationId: t.Optional(t.String({
|
|
16
|
+
description: "Shift Labs organization ID (required for transcription actions)",
|
|
17
|
+
env: "SHIFT_LABS_ORG_ID",
|
|
18
|
+
})),
|
|
12
19
|
}));
|
|
20
|
+
registerProjectActions(rl);
|
|
13
21
|
registerIssueActions(rl);
|
|
22
|
+
registerIssueViewActions(rl);
|
|
14
23
|
registerPageActions(rl);
|
|
24
|
+
registerTranscriptionActions(rl);
|
|
15
25
|
}
|