runline 0.12.0 → 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.
- 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 +6 -0
- package/dist/plugins/shiftLabs/src/shared.js +2 -0
- package/dist/plugins/shiftLabs/src/transcription.js +203 -0
- package/package.json +1 -1
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
* the bare ID and normalize. The response always includes a
|
|
23
23
|
* convenience `contactId` field stripped from `resourceName`.
|
|
24
24
|
*/
|
|
25
|
+
import * as t from "typebox";
|
|
25
26
|
import { googleAccessToken } from "../../_shared/googleAuth.js";
|
|
27
|
+
import { Id, NonEmptyString, PositiveInteger, stringEnum, } from "../../_shared/googleSchemas.js";
|
|
26
28
|
// ─── Fields ─────────────────────────────────────────────────────
|
|
27
29
|
/**
|
|
28
30
|
* Every `personFields` value supported by People API get/list calls.
|
|
@@ -279,6 +281,128 @@ function attachContactId(obj) {
|
|
|
279
281
|
}
|
|
280
282
|
// ─── Plugin ──────────────────────────────────────────────────────
|
|
281
283
|
const SCOPES = ["https://www.googleapis.com/auth/contacts"];
|
|
284
|
+
const strictObject = (properties, options = {}) => t.Object(properties, { ...options, additionalProperties: false });
|
|
285
|
+
const optionalString = (description) => t.Optional(t.String(description ? { description } : {}));
|
|
286
|
+
const optionalBoolean = t.Optional(t.Boolean());
|
|
287
|
+
const personField = stringEnum([...ALL_PERSON_FIELDS, "*"]);
|
|
288
|
+
const personFields = t.Optional(t.Union([t.String(), t.Array(personField, { minItems: 1 })]));
|
|
289
|
+
const structuredDate = strictObject({
|
|
290
|
+
year: t.Optional(t.Integer({ minimum: 0 })),
|
|
291
|
+
month: t.Integer({ minimum: 1, maximum: 12 }),
|
|
292
|
+
day: t.Integer({ minimum: 1, maximum: 31 }),
|
|
293
|
+
});
|
|
294
|
+
const contactDate = t.Union([NonEmptyString, structuredDate]);
|
|
295
|
+
const typedValue = strictObject({
|
|
296
|
+
value: NonEmptyString,
|
|
297
|
+
type: optionalString(),
|
|
298
|
+
});
|
|
299
|
+
const relation = strictObject({
|
|
300
|
+
person: NonEmptyString,
|
|
301
|
+
type: optionalString(),
|
|
302
|
+
});
|
|
303
|
+
const contactEvent = strictObject({
|
|
304
|
+
date: contactDate,
|
|
305
|
+
type: optionalString(),
|
|
306
|
+
});
|
|
307
|
+
const userDefined = strictObject({ key: NonEmptyString, value: t.String() });
|
|
308
|
+
// These two People API resources are intentionally extensible. Known fields are
|
|
309
|
+
// typed, while additional provider fields remain available for forward
|
|
310
|
+
// compatibility and parity with the plugin's existing passthrough behavior.
|
|
311
|
+
const address = t.Object({
|
|
312
|
+
formattedValue: optionalString(),
|
|
313
|
+
type: optionalString(),
|
|
314
|
+
poBox: optionalString(),
|
|
315
|
+
streetAddress: optionalString(),
|
|
316
|
+
extendedAddress: optionalString(),
|
|
317
|
+
city: optionalString(),
|
|
318
|
+
region: optionalString(),
|
|
319
|
+
postalCode: optionalString(),
|
|
320
|
+
country: optionalString(),
|
|
321
|
+
countryCode: optionalString(),
|
|
322
|
+
}, { additionalProperties: true });
|
|
323
|
+
const organization = t.Object({
|
|
324
|
+
name: optionalString(),
|
|
325
|
+
title: optionalString(),
|
|
326
|
+
department: optionalString(),
|
|
327
|
+
type: optionalString(),
|
|
328
|
+
symbol: optionalString(),
|
|
329
|
+
domain: optionalString(),
|
|
330
|
+
location: optionalString(),
|
|
331
|
+
jobDescription: optionalString(),
|
|
332
|
+
phoneticName: optionalString(),
|
|
333
|
+
costCenter: optionalString(),
|
|
334
|
+
fullTimeEquivalentMillipercent: t.Optional(t.Integer({ minimum: 0, maximum: 100_000 })),
|
|
335
|
+
startDate: t.Optional(structuredDate),
|
|
336
|
+
endDate: t.Optional(structuredDate),
|
|
337
|
+
current: optionalBoolean,
|
|
338
|
+
}, { additionalProperties: true });
|
|
339
|
+
const clientData = strictObject({ key: NonEmptyString, value: t.String() });
|
|
340
|
+
const contactWritableFields = {
|
|
341
|
+
givenName: optionalString(),
|
|
342
|
+
familyName: optionalString(),
|
|
343
|
+
middleName: optionalString(),
|
|
344
|
+
honorificPrefix: optionalString(),
|
|
345
|
+
honorificSuffix: optionalString(),
|
|
346
|
+
phoneNumbers: t.Optional(t.Array(typedValue)),
|
|
347
|
+
emailAddresses: t.Optional(t.Array(typedValue)),
|
|
348
|
+
addresses: t.Optional(t.Array(address)),
|
|
349
|
+
organizations: t.Optional(t.Array(organization)),
|
|
350
|
+
relations: t.Optional(t.Array(relation)),
|
|
351
|
+
urls: t.Optional(t.Array(typedValue)),
|
|
352
|
+
events: t.Optional(t.Array(contactEvent)),
|
|
353
|
+
birthday: t.Optional(contactDate),
|
|
354
|
+
biography: optionalString(),
|
|
355
|
+
userDefined: t.Optional(t.Array(userDefined)),
|
|
356
|
+
groups: t.Optional(t.Array(NonEmptyString)),
|
|
357
|
+
};
|
|
358
|
+
const writableContactKeys = Object.keys(contactWritableFields);
|
|
359
|
+
const contactSchemas = {
|
|
360
|
+
create: strictObject(contactWritableFields),
|
|
361
|
+
get: strictObject({ contactId: Id, fields: personFields }),
|
|
362
|
+
list: strictObject({
|
|
363
|
+
query: optionalString(),
|
|
364
|
+
fields: personFields,
|
|
365
|
+
sortOrder: t.Optional(stringEnum([
|
|
366
|
+
"LAST_MODIFIED_ASCENDING",
|
|
367
|
+
"LAST_MODIFIED_DESCENDING",
|
|
368
|
+
"FIRST_NAME_ASCENDING",
|
|
369
|
+
"LAST_NAME_ASCENDING",
|
|
370
|
+
])),
|
|
371
|
+
returnAll: optionalBoolean,
|
|
372
|
+
maxResults: t.Optional(PositiveInteger),
|
|
373
|
+
pageToken: optionalString(),
|
|
374
|
+
}),
|
|
375
|
+
update: strictObject({
|
|
376
|
+
contactId: Id,
|
|
377
|
+
etag: optionalString(),
|
|
378
|
+
fields: personFields,
|
|
379
|
+
...contactWritableFields,
|
|
380
|
+
}, { anyOf: writableContactKeys.map((key) => ({ required: [key] })) }),
|
|
381
|
+
delete: strictObject({ contactId: Id }),
|
|
382
|
+
};
|
|
383
|
+
const groupSchemas = {
|
|
384
|
+
list: strictObject({
|
|
385
|
+
returnAll: optionalBoolean,
|
|
386
|
+
maxResults: t.Optional(PositiveInteger),
|
|
387
|
+
pageToken: optionalString(),
|
|
388
|
+
syncToken: optionalString(),
|
|
389
|
+
}),
|
|
390
|
+
get: strictObject({
|
|
391
|
+
groupId: Id,
|
|
392
|
+
maxMembers: t.Optional(t.Integer({ minimum: 0 })),
|
|
393
|
+
}),
|
|
394
|
+
create: strictObject({
|
|
395
|
+
name: NonEmptyString,
|
|
396
|
+
clientData: t.Optional(t.Array(clientData)),
|
|
397
|
+
}),
|
|
398
|
+
update: strictObject({
|
|
399
|
+
groupId: Id,
|
|
400
|
+
name: optionalString(),
|
|
401
|
+
clientData: t.Optional(t.Array(clientData)),
|
|
402
|
+
etag: optionalString(),
|
|
403
|
+
}, { anyOf: [{ required: ["name"] }, { required: ["clientData"] }] }),
|
|
404
|
+
delete: strictObject({ groupId: Id, deleteContacts: optionalBoolean }),
|
|
405
|
+
};
|
|
282
406
|
export default function googleContacts(rl) {
|
|
283
407
|
rl.setName("googleContacts");
|
|
284
408
|
rl.setVersion("0.1.0");
|
|
@@ -328,60 +452,7 @@ export default function googleContacts(rl) {
|
|
|
328
452
|
rl.registerAction("contact.create", {
|
|
329
453
|
access: "write",
|
|
330
454
|
description: "Create a new contact",
|
|
331
|
-
inputSchema:
|
|
332
|
-
givenName: { type: "string", required: false },
|
|
333
|
-
familyName: { type: "string", required: false },
|
|
334
|
-
middleName: { type: "string", required: false },
|
|
335
|
-
honorificPrefix: { type: "string", required: false },
|
|
336
|
-
honorificSuffix: { type: "string", required: false },
|
|
337
|
-
phoneNumbers: {
|
|
338
|
-
type: "array",
|
|
339
|
-
required: false,
|
|
340
|
-
description: "[{value, type?}]",
|
|
341
|
-
},
|
|
342
|
-
emailAddresses: {
|
|
343
|
-
type: "array",
|
|
344
|
-
required: false,
|
|
345
|
-
description: "[{value, type?}]",
|
|
346
|
-
},
|
|
347
|
-
addresses: {
|
|
348
|
-
type: "array",
|
|
349
|
-
required: false,
|
|
350
|
-
description: "[{formattedValue?, streetAddress?, city?, region?, postalCode?, country?, type?}]",
|
|
351
|
-
},
|
|
352
|
-
organizations: {
|
|
353
|
-
type: "array",
|
|
354
|
-
required: false,
|
|
355
|
-
description: "[{name, title?, department?, type?}]",
|
|
356
|
-
},
|
|
357
|
-
relations: {
|
|
358
|
-
type: "array",
|
|
359
|
-
required: false,
|
|
360
|
-
description: "[{person, type?}]",
|
|
361
|
-
},
|
|
362
|
-
urls: { type: "array", required: false },
|
|
363
|
-
events: {
|
|
364
|
-
type: "array",
|
|
365
|
-
required: false,
|
|
366
|
-
description: "[{date, type?}] — date can be ISO string or {year, month, day}",
|
|
367
|
-
},
|
|
368
|
-
birthday: {
|
|
369
|
-
type: "string",
|
|
370
|
-
required: false,
|
|
371
|
-
description: "ISO date string or {year, month, day}",
|
|
372
|
-
},
|
|
373
|
-
biography: { type: "string", required: false },
|
|
374
|
-
userDefined: {
|
|
375
|
-
type: "array",
|
|
376
|
-
required: false,
|
|
377
|
-
description: "[{key, value}] — custom key/value pairs",
|
|
378
|
-
},
|
|
379
|
-
groups: {
|
|
380
|
-
type: "array",
|
|
381
|
-
required: false,
|
|
382
|
-
description: "Group IDs or full contactGroups/… resource names",
|
|
383
|
-
},
|
|
384
|
-
},
|
|
455
|
+
inputSchema: contactSchemas.create,
|
|
385
456
|
async execute(input, ctx) {
|
|
386
457
|
const p = (input ?? {});
|
|
387
458
|
const { body } = buildPersonBody(p);
|
|
@@ -392,18 +463,7 @@ export default function googleContacts(rl) {
|
|
|
392
463
|
rl.registerAction("contact.get", {
|
|
393
464
|
access: "read",
|
|
394
465
|
description: "Get a contact by ID",
|
|
395
|
-
inputSchema:
|
|
396
|
-
contactId: {
|
|
397
|
-
type: "string",
|
|
398
|
-
required: true,
|
|
399
|
-
description: "Bare ID or full people/… resource name",
|
|
400
|
-
},
|
|
401
|
-
fields: {
|
|
402
|
-
type: "string",
|
|
403
|
-
required: false,
|
|
404
|
-
description: "'*' (all), comma-separated string, or array of People-API field names (default: names, emailAddresses, phoneNumbers)",
|
|
405
|
-
},
|
|
406
|
-
},
|
|
466
|
+
inputSchema: contactSchemas.get,
|
|
407
467
|
async execute(input, ctx) {
|
|
408
468
|
const p = (input ?? {});
|
|
409
469
|
const resource = normalizeContactResource(p.contactId);
|
|
@@ -414,22 +474,7 @@ export default function googleContacts(rl) {
|
|
|
414
474
|
rl.registerAction("contact.list", {
|
|
415
475
|
access: "read",
|
|
416
476
|
description: "List contacts (people/me/connections) or search them. When `query` is set, hits people:searchContacts; otherwise returns the user's connections.",
|
|
417
|
-
inputSchema:
|
|
418
|
-
query: {
|
|
419
|
-
type: "string",
|
|
420
|
-
required: false,
|
|
421
|
-
description: "If set, uses people:searchContacts instead of connections.list",
|
|
422
|
-
},
|
|
423
|
-
fields: { type: "string", required: false },
|
|
424
|
-
sortOrder: {
|
|
425
|
-
type: "string",
|
|
426
|
-
required: false,
|
|
427
|
-
description: "LAST_MODIFIED_ASCENDING | LAST_MODIFIED_DESCENDING | FIRST_NAME_ASCENDING | LAST_NAME_ASCENDING (connections.list only)",
|
|
428
|
-
},
|
|
429
|
-
returnAll: { type: "boolean", required: false },
|
|
430
|
-
maxResults: { type: "number", required: false },
|
|
431
|
-
pageToken: { type: "string", required: false },
|
|
432
|
-
},
|
|
477
|
+
inputSchema: contactSchemas.list,
|
|
433
478
|
async execute(input, ctx) {
|
|
434
479
|
const p = (input ?? {});
|
|
435
480
|
const useSearch = typeof p.query === "string" && p.query.length > 0;
|
|
@@ -484,36 +529,7 @@ export default function googleContacts(rl) {
|
|
|
484
529
|
rl.registerAction("contact.update", {
|
|
485
530
|
access: "write",
|
|
486
531
|
description: "Update a contact. Only supplied fields are sent; etag is resolved automatically if not provided.",
|
|
487
|
-
inputSchema:
|
|
488
|
-
contactId: { type: "string", required: true },
|
|
489
|
-
etag: {
|
|
490
|
-
type: "string",
|
|
491
|
-
required: false,
|
|
492
|
-
description: "Optimistic-concurrency tag. If omitted, the plugin fetches the latest etag first.",
|
|
493
|
-
},
|
|
494
|
-
fields: {
|
|
495
|
-
type: "string",
|
|
496
|
-
required: false,
|
|
497
|
-
description: "personFields projection on the response (same semantics as contact.get)",
|
|
498
|
-
},
|
|
499
|
-
// Writable fields
|
|
500
|
-
givenName: { type: "string", required: false },
|
|
501
|
-
familyName: { type: "string", required: false },
|
|
502
|
-
middleName: { type: "string", required: false },
|
|
503
|
-
honorificPrefix: { type: "string", required: false },
|
|
504
|
-
honorificSuffix: { type: "string", required: false },
|
|
505
|
-
phoneNumbers: { type: "array", required: false },
|
|
506
|
-
emailAddresses: { type: "array", required: false },
|
|
507
|
-
addresses: { type: "array", required: false },
|
|
508
|
-
organizations: { type: "array", required: false },
|
|
509
|
-
relations: { type: "array", required: false },
|
|
510
|
-
urls: { type: "array", required: false },
|
|
511
|
-
events: { type: "array", required: false },
|
|
512
|
-
birthday: { type: "string", required: false },
|
|
513
|
-
biography: { type: "string", required: false },
|
|
514
|
-
userDefined: { type: "array", required: false },
|
|
515
|
-
groups: { type: "array", required: false },
|
|
516
|
-
},
|
|
532
|
+
inputSchema: contactSchemas.update,
|
|
517
533
|
async execute(input, ctx) {
|
|
518
534
|
const p = (input ?? {});
|
|
519
535
|
const resource = normalizeContactResource(p.contactId);
|
|
@@ -539,7 +555,7 @@ export default function googleContacts(rl) {
|
|
|
539
555
|
rl.registerAction("contact.delete", {
|
|
540
556
|
access: "write",
|
|
541
557
|
description: "Delete a contact",
|
|
542
|
-
inputSchema:
|
|
558
|
+
inputSchema: contactSchemas.delete,
|
|
543
559
|
async execute(input, ctx) {
|
|
544
560
|
const p = (input ?? {});
|
|
545
561
|
const resource = normalizeContactResource(p.contactId);
|
|
@@ -551,12 +567,7 @@ export default function googleContacts(rl) {
|
|
|
551
567
|
rl.registerAction("group.list", {
|
|
552
568
|
access: "read",
|
|
553
569
|
description: "List contact groups (including system groups like 'myContacts' and 'starred')",
|
|
554
|
-
inputSchema:
|
|
555
|
-
returnAll: { type: "boolean", required: false },
|
|
556
|
-
maxResults: { type: "number", required: false },
|
|
557
|
-
pageToken: { type: "string", required: false },
|
|
558
|
-
syncToken: { type: "string", required: false },
|
|
559
|
-
},
|
|
570
|
+
inputSchema: groupSchemas.list,
|
|
560
571
|
async execute(input, ctx) {
|
|
561
572
|
const p = (input ?? {});
|
|
562
573
|
const qs = {};
|
|
@@ -575,14 +586,7 @@ export default function googleContacts(rl) {
|
|
|
575
586
|
rl.registerAction("group.get", {
|
|
576
587
|
access: "read",
|
|
577
588
|
description: "Get a contact group by ID",
|
|
578
|
-
inputSchema:
|
|
579
|
-
groupId: { type: "string", required: true },
|
|
580
|
-
maxMembers: {
|
|
581
|
-
type: "number",
|
|
582
|
-
required: false,
|
|
583
|
-
description: "Include up to N member resourceNames in the response",
|
|
584
|
-
},
|
|
585
|
-
},
|
|
589
|
+
inputSchema: groupSchemas.get,
|
|
586
590
|
async execute(input, ctx) {
|
|
587
591
|
const p = (input ?? {});
|
|
588
592
|
const resource = normalizeGroupResource(p.groupId);
|
|
@@ -595,14 +599,7 @@ export default function googleContacts(rl) {
|
|
|
595
599
|
rl.registerAction("group.create", {
|
|
596
600
|
access: "write",
|
|
597
601
|
description: "Create a contact group",
|
|
598
|
-
inputSchema:
|
|
599
|
-
name: { type: "string", required: true },
|
|
600
|
-
clientData: {
|
|
601
|
-
type: "array",
|
|
602
|
-
required: false,
|
|
603
|
-
description: "[{key, value}] — app-private metadata",
|
|
604
|
-
},
|
|
605
|
-
},
|
|
602
|
+
inputSchema: groupSchemas.create,
|
|
606
603
|
async execute(input, ctx) {
|
|
607
604
|
const p = (input ?? {});
|
|
608
605
|
const body = {
|
|
@@ -617,12 +614,7 @@ export default function googleContacts(rl) {
|
|
|
617
614
|
rl.registerAction("group.update", {
|
|
618
615
|
access: "write",
|
|
619
616
|
description: "Update a contact group. Pass a fresh `etag` or let the plugin resolve it automatically.",
|
|
620
|
-
inputSchema:
|
|
621
|
-
groupId: { type: "string", required: true },
|
|
622
|
-
name: { type: "string", required: false },
|
|
623
|
-
clientData: { type: "array", required: false },
|
|
624
|
-
etag: { type: "string", required: false },
|
|
625
|
-
},
|
|
617
|
+
inputSchema: groupSchemas.update,
|
|
626
618
|
async execute(input, ctx) {
|
|
627
619
|
const p = (input ?? {});
|
|
628
620
|
const resource = normalizeGroupResource(p.groupId);
|
|
@@ -653,10 +645,7 @@ export default function googleContacts(rl) {
|
|
|
653
645
|
rl.registerAction("group.delete", {
|
|
654
646
|
access: "write",
|
|
655
647
|
description: "Delete a contact group. Pass `deleteContacts=true` to also delete every contact in the group.",
|
|
656
|
-
inputSchema:
|
|
657
|
-
groupId: { type: "string", required: true },
|
|
658
|
-
deleteContacts: { type: "boolean", required: false },
|
|
659
|
-
},
|
|
648
|
+
inputSchema: groupSchemas.delete,
|
|
660
649
|
async execute(input, ctx) {
|
|
661
650
|
const p = (input ?? {});
|
|
662
651
|
const resource = normalizeGroupResource(p.groupId);
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as t from "typebox";
|
|
2
|
+
import { DocumentInput, DRIVE_BASE, docsRequest, extractDocumentId, flattenBodyText, RawGoogleObject, STRICT_OBJECT, WriteControl, } from "./shared.js";
|
|
2
3
|
export function registerDocumentsActions(rl) {
|
|
3
4
|
rl.registerAction("document.create", {
|
|
4
5
|
access: "write",
|
|
5
6
|
description: "Create a new Google Doc, optionally in a specific Drive folder (goes through the Drive API; needs drive.file scope).",
|
|
6
|
-
inputSchema: {
|
|
7
|
-
title: {
|
|
8
|
-
folderId: {
|
|
9
|
-
|
|
10
|
-
required: false,
|
|
7
|
+
inputSchema: t.Object({
|
|
8
|
+
title: t.String({ minLength: 1 }),
|
|
9
|
+
folderId: t.Optional(t.String({
|
|
10
|
+
minLength: 1,
|
|
11
11
|
description: "Parent folder in Drive. Omit to place in My Drive root.",
|
|
12
|
-
},
|
|
13
|
-
},
|
|
12
|
+
})),
|
|
13
|
+
}, STRICT_OBJECT),
|
|
14
14
|
async execute(input, ctx) {
|
|
15
15
|
const p = (input ?? {});
|
|
16
16
|
const body = {
|
|
@@ -26,9 +26,7 @@ export function registerDocumentsActions(rl) {
|
|
|
26
26
|
rl.registerAction("document.createBlank", {
|
|
27
27
|
access: "write",
|
|
28
28
|
description: "Create a blank Google Doc through the native Docs API. Use document.create when you need Drive folder placement.",
|
|
29
|
-
inputSchema: {
|
|
30
|
-
title: { type: "string", required: true },
|
|
31
|
-
},
|
|
29
|
+
inputSchema: t.Object({ title: t.String({ minLength: 1 }) }, STRICT_OBJECT),
|
|
32
30
|
async execute(input, ctx) {
|
|
33
31
|
const p = (input ?? {});
|
|
34
32
|
return docsRequest(ctx, "POST", "/documents", { title: p.title });
|
|
@@ -37,24 +35,19 @@ export function registerDocumentsActions(rl) {
|
|
|
37
35
|
rl.registerAction("document.get", {
|
|
38
36
|
access: "read",
|
|
39
37
|
description: "Get a document. Accepts a bare ID or a docs.google.com URL. `simple=true` collapses the body to plain text.",
|
|
40
|
-
inputSchema: {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
description: "
|
|
51
|
-
},
|
|
52
|
-
|
|
53
|
-
type: "boolean",
|
|
54
|
-
required: false,
|
|
55
|
-
description: "Return content for all tabs in document.tabs instead of only first-tab legacy fields.",
|
|
56
|
-
},
|
|
57
|
-
},
|
|
38
|
+
inputSchema: t.Object({
|
|
39
|
+
...DocumentInput,
|
|
40
|
+
simple: t.Optional(t.Boolean()),
|
|
41
|
+
suggestionsViewMode: t.Optional(t.Union([
|
|
42
|
+
t.Literal("DEFAULT_FOR_CURRENT_ACCESS"),
|
|
43
|
+
t.Literal("SUGGESTIONS_INLINE"),
|
|
44
|
+
t.Literal("PREVIEW_SUGGESTIONS_ACCEPTED"),
|
|
45
|
+
t.Literal("PREVIEW_WITHOUT_SUGGESTIONS"),
|
|
46
|
+
])),
|
|
47
|
+
includeTabsContent: t.Optional(t.Boolean({
|
|
48
|
+
description: "Return content for all tabs instead of only first-tab legacy fields.",
|
|
49
|
+
})),
|
|
50
|
+
}, STRICT_OBJECT),
|
|
58
51
|
async execute(input, ctx) {
|
|
59
52
|
const p = (input ?? {});
|
|
60
53
|
const documentId = extractDocumentId(p.document);
|
|
@@ -72,15 +65,11 @@ export function registerDocumentsActions(rl) {
|
|
|
72
65
|
rl.registerAction("document.batchUpdate", {
|
|
73
66
|
access: "write",
|
|
74
67
|
description: "Raw passthrough to documents.batchUpdate — pass a full `requests` array for atomic multi-edit operations.",
|
|
75
|
-
inputSchema: {
|
|
76
|
-
|
|
77
|
-
requests: {
|
|
78
|
-
writeControl:
|
|
79
|
-
|
|
80
|
-
required: false,
|
|
81
|
-
description: "{requiredRevisionId} | {targetRevisionId}",
|
|
82
|
-
},
|
|
83
|
-
},
|
|
68
|
+
inputSchema: t.Object({
|
|
69
|
+
...DocumentInput,
|
|
70
|
+
requests: t.Array(RawGoogleObject, { minItems: 1 }),
|
|
71
|
+
writeControl: t.Optional(WriteControl),
|
|
72
|
+
}, STRICT_OBJECT),
|
|
84
73
|
async execute(input, ctx) {
|
|
85
74
|
const p = (input ?? {});
|
|
86
75
|
const documentId = extractDocumentId(p.document);
|
|
@@ -1,40 +1,50 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as t from "typebox";
|
|
2
|
+
import { compact, DocumentInput, extractDocumentId, PositivePoints, RangeInput, RawGoogleObject, runBatchUpdate, STRICT_OBJECT, } from "./shared.js";
|
|
2
3
|
export function registerFormattingActions(rl) {
|
|
3
4
|
rl.registerAction("document.updateParagraphStyle", {
|
|
4
5
|
access: "write",
|
|
5
6
|
description: "Apply paragraph styling (alignment, named style, indents, spacing, direction) to the paragraphs intersecting the range.",
|
|
6
|
-
inputSchema: {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
namedStyleType:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
7
|
+
inputSchema: t.Object({
|
|
8
|
+
...DocumentInput,
|
|
9
|
+
...RangeInput,
|
|
10
|
+
alignment: t.Optional(t.Union([
|
|
11
|
+
t.Literal("START"),
|
|
12
|
+
t.Literal("CENTER"),
|
|
13
|
+
t.Literal("END"),
|
|
14
|
+
t.Literal("JUSTIFIED"),
|
|
15
|
+
])),
|
|
16
|
+
namedStyleType: t.Optional(t.Union([
|
|
17
|
+
t.Literal("NORMAL_TEXT"),
|
|
18
|
+
t.Literal("TITLE"),
|
|
19
|
+
t.Literal("SUBTITLE"),
|
|
20
|
+
t.Literal("HEADING_1"),
|
|
21
|
+
t.Literal("HEADING_2"),
|
|
22
|
+
t.Literal("HEADING_3"),
|
|
23
|
+
t.Literal("HEADING_4"),
|
|
24
|
+
t.Literal("HEADING_5"),
|
|
25
|
+
t.Literal("HEADING_6"),
|
|
26
|
+
])),
|
|
27
|
+
direction: t.Optional(t.Union([t.Literal("LEFT_TO_RIGHT"), t.Literal("RIGHT_TO_LEFT")])),
|
|
28
|
+
indentFirstLinePt: t.Optional(PositivePoints),
|
|
29
|
+
indentStartPt: t.Optional(PositivePoints),
|
|
30
|
+
indentEndPt: t.Optional(PositivePoints),
|
|
31
|
+
spaceAbovePt: t.Optional(PositivePoints),
|
|
32
|
+
spaceBelowPt: t.Optional(PositivePoints),
|
|
33
|
+
lineSpacing: t.Optional(t.Number({ minimum: 0 })),
|
|
34
|
+
}, {
|
|
35
|
+
...STRICT_OBJECT,
|
|
36
|
+
anyOf: [
|
|
37
|
+
{ required: ["alignment"] },
|
|
38
|
+
{ required: ["namedStyleType"] },
|
|
39
|
+
{ required: ["direction"] },
|
|
40
|
+
{ required: ["indentFirstLinePt"] },
|
|
41
|
+
{ required: ["indentStartPt"] },
|
|
42
|
+
{ required: ["indentEndPt"] },
|
|
43
|
+
{ required: ["spaceAbovePt"] },
|
|
44
|
+
{ required: ["spaceBelowPt"] },
|
|
45
|
+
{ required: ["lineSpacing"] },
|
|
46
|
+
],
|
|
47
|
+
}),
|
|
38
48
|
async execute(input, ctx) {
|
|
39
49
|
const p = (input ?? {});
|
|
40
50
|
const documentId = extractDocumentId(p.document);
|
|
@@ -99,20 +109,12 @@ export function registerFormattingActions(rl) {
|
|
|
99
109
|
rl.registerAction("document.updateNamedStyle", {
|
|
100
110
|
access: "write",
|
|
101
111
|
description: "Update a named style such as NORMAL_TEXT, TITLE, or HEADING_1 using a Docs API NamedStyle object.",
|
|
102
|
-
inputSchema: {
|
|
103
|
-
|
|
104
|
-
namedStyle:
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
},
|
|
109
|
-
fields: {
|
|
110
|
-
type: "string",
|
|
111
|
-
required: true,
|
|
112
|
-
description: "Field mask such as textStyle.bold or paragraphStyle.alignment.",
|
|
113
|
-
},
|
|
114
|
-
tabId: { type: "string", required: false },
|
|
115
|
-
},
|
|
112
|
+
inputSchema: t.Object({
|
|
113
|
+
...DocumentInput,
|
|
114
|
+
namedStyle: RawGoogleObject,
|
|
115
|
+
fields: t.String({ minLength: 1 }),
|
|
116
|
+
tabId: t.Optional(t.String({ minLength: 1 })),
|
|
117
|
+
}, STRICT_OBJECT),
|
|
116
118
|
async execute(input, ctx) {
|
|
117
119
|
const p = (input ?? {});
|
|
118
120
|
const documentId = extractDocumentId(p.document);
|
|
@@ -1,22 +1,21 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as t from "typebox";
|
|
2
|
+
import { buildLocation, DocumentInput, extractDocumentId, LOCATION_REQUIREMENT, LocationInput, PositivePoints, runBatchUpdate, STRICT_OBJECT, } from "./shared.js";
|
|
3
|
+
const PublicImageUri = t.String({
|
|
4
|
+
minLength: 1,
|
|
5
|
+
pattern: "^https?://",
|
|
6
|
+
description: "Publicly fetchable HTTP(S) image URI",
|
|
7
|
+
});
|
|
2
8
|
export function registerImagesActions(rl) {
|
|
3
9
|
rl.registerAction("document.insertInlineImage", {
|
|
4
10
|
access: "write",
|
|
5
11
|
description: "Insert an inline image at the given location. `uri` must point to a publicly fetchable image.",
|
|
6
|
-
inputSchema: {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
index: { type: "number", required: false },
|
|
14
|
-
uri: { type: "string", required: true },
|
|
15
|
-
widthPt: { type: "number", required: false },
|
|
16
|
-
heightPt: { type: "number", required: false },
|
|
17
|
-
segmentId: { type: "string", required: false },
|
|
18
|
-
tabId: { type: "string", required: false },
|
|
19
|
-
},
|
|
12
|
+
inputSchema: t.Object({
|
|
13
|
+
...DocumentInput,
|
|
14
|
+
...LocationInput,
|
|
15
|
+
uri: PublicImageUri,
|
|
16
|
+
widthPt: t.Optional(PositivePoints),
|
|
17
|
+
heightPt: t.Optional(PositivePoints),
|
|
18
|
+
}, { ...STRICT_OBJECT, anyOf: LOCATION_REQUIREMENT }),
|
|
20
19
|
async execute(input, ctx) {
|
|
21
20
|
const p = (input ?? {});
|
|
22
21
|
const documentId = extractDocumentId(p.document);
|
|
@@ -39,17 +38,13 @@ export function registerImagesActions(rl) {
|
|
|
39
38
|
rl.registerAction("document.replaceImage", {
|
|
40
39
|
access: "write",
|
|
41
40
|
description: "Replace an existing image (identified by its inline-object id) with a new image from a publicly fetchable URI.",
|
|
42
|
-
inputSchema: {
|
|
43
|
-
|
|
44
|
-
imageObjectId: {
|
|
45
|
-
uri:
|
|
46
|
-
imageReplaceMethod:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
description: "CENTER_CROP (default) | (others as Docs API adds them)",
|
|
50
|
-
},
|
|
51
|
-
tabId: { type: "string", required: false },
|
|
52
|
-
},
|
|
41
|
+
inputSchema: t.Object({
|
|
42
|
+
...DocumentInput,
|
|
43
|
+
imageObjectId: t.String({ minLength: 1 }),
|
|
44
|
+
uri: PublicImageUri,
|
|
45
|
+
imageReplaceMethod: t.Optional(t.Literal("CENTER_CROP")),
|
|
46
|
+
tabId: t.Optional(t.String({ minLength: 1 })),
|
|
47
|
+
}, STRICT_OBJECT),
|
|
53
48
|
async execute(input, ctx) {
|
|
54
49
|
const p = (input ?? {});
|
|
55
50
|
const documentId = extractDocumentId(p.document);
|