@sentry/junior-google 0.243.0 → 0.245.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/README.md +38 -23
- package/dist/config.d.ts +3 -2
- package/dist/credentials.d.ts +31 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +433 -106
- package/dist/tools/files.d.ts +76 -0
- package/dist/tools/{list-doc-comments.d.ts → list-file-comments.d.ts} +7 -7
- package/dist/tools/read-doc.d.ts +1 -1
- package/dist/tools/read-sheet.d.ts +145 -0
- package/dist/tools/read-slides.d.ts +144 -0
- package/dist/tools/{search-docs.d.ts → search-files.d.ts} +11 -8
- package/dist/tools/shared.d.ts +2 -1
- package/package.json +2 -2
- package/dist/tools/docs.d.ts +0 -37
package/dist/index.js
CHANGED
|
@@ -434,58 +434,93 @@ import {
|
|
|
434
434
|
EgressPolicyDenied
|
|
435
435
|
} from "@sentry/junior-plugin-api";
|
|
436
436
|
var GOOGLE_API_DOMAIN = "www.googleapis.com";
|
|
437
|
+
var GOOGLE_SHEETS_API_DOMAIN = "sheets.googleapis.com";
|
|
438
|
+
var GOOGLE_SLIDES_API_DOMAIN = "slides.googleapis.com";
|
|
439
|
+
var GOOGLE_API_DOMAINS = [
|
|
440
|
+
GOOGLE_API_DOMAIN,
|
|
441
|
+
GOOGLE_SHEETS_API_DOMAIN,
|
|
442
|
+
GOOGLE_SLIDES_API_DOMAIN
|
|
443
|
+
];
|
|
437
444
|
var GRANT_NAME = "account";
|
|
438
445
|
var LEASE_SAFETY_MS = 6e4;
|
|
439
446
|
var GOOGLE_OPERATIONS = {
|
|
440
447
|
"google.calendar.event.create": {
|
|
441
448
|
access: "write",
|
|
449
|
+
host: GOOGLE_API_DOMAIN,
|
|
442
450
|
method: "POST",
|
|
443
451
|
path: /^\/calendar\/v3\/calendars\/primary\/events$/
|
|
444
452
|
},
|
|
445
453
|
"google.calendar.event.delete": {
|
|
446
454
|
access: "write",
|
|
455
|
+
host: GOOGLE_API_DOMAIN,
|
|
447
456
|
method: "DELETE",
|
|
448
457
|
path: /^\/calendar\/v3\/calendars\/primary\/events\/[A-Za-z0-9_]+$/
|
|
449
458
|
},
|
|
450
459
|
"google.calendar.event.get": {
|
|
451
460
|
access: "read",
|
|
461
|
+
host: GOOGLE_API_DOMAIN,
|
|
452
462
|
method: "GET",
|
|
453
463
|
path: /^\/calendar\/v3\/calendars\/primary\/events\/[A-Za-z0-9_]+$/
|
|
454
464
|
},
|
|
455
465
|
"google.calendar.event.update": {
|
|
456
466
|
access: "write",
|
|
467
|
+
host: GOOGLE_API_DOMAIN,
|
|
457
468
|
method: "PATCH",
|
|
458
469
|
path: /^\/calendar\/v3\/calendars\/primary\/events\/[A-Za-z0-9_]+$/
|
|
459
470
|
},
|
|
460
471
|
"google.calendar.events.list": {
|
|
461
472
|
access: "read",
|
|
473
|
+
host: GOOGLE_API_DOMAIN,
|
|
462
474
|
method: "GET",
|
|
463
475
|
path: /^\/calendar\/v3\/calendars\/[^/]+\/events$/
|
|
464
476
|
},
|
|
465
477
|
"google.calendar.freebusy.query": {
|
|
466
478
|
access: "read",
|
|
479
|
+
host: GOOGLE_API_DOMAIN,
|
|
467
480
|
method: "POST",
|
|
468
481
|
path: /^\/calendar\/v3\/freeBusy$/
|
|
469
482
|
},
|
|
470
483
|
"google.drive.comments.list": {
|
|
471
484
|
access: "read",
|
|
485
|
+
host: GOOGLE_API_DOMAIN,
|
|
472
486
|
method: "GET",
|
|
473
487
|
path: /^\/drive\/v3\/files\/[A-Za-z0-9_-]+\/comments$/
|
|
474
488
|
},
|
|
475
489
|
"google.drive.file.export": {
|
|
476
490
|
access: "read",
|
|
491
|
+
host: GOOGLE_API_DOMAIN,
|
|
477
492
|
method: "GET",
|
|
478
493
|
path: /^\/drive\/v3\/files\/[A-Za-z0-9_-]+\/export$/
|
|
479
494
|
},
|
|
480
495
|
"google.drive.file.get": {
|
|
481
496
|
access: "read",
|
|
497
|
+
host: GOOGLE_API_DOMAIN,
|
|
482
498
|
method: "GET",
|
|
483
499
|
path: /^\/drive\/v3\/files\/[A-Za-z0-9_-]+$/
|
|
484
500
|
},
|
|
485
501
|
"google.drive.files.list": {
|
|
486
502
|
access: "read",
|
|
503
|
+
host: GOOGLE_API_DOMAIN,
|
|
487
504
|
method: "GET",
|
|
488
505
|
path: /^\/drive\/v3\/files$/
|
|
506
|
+
},
|
|
507
|
+
"google.sheets.spreadsheet.get": {
|
|
508
|
+
access: "read",
|
|
509
|
+
host: GOOGLE_SHEETS_API_DOMAIN,
|
|
510
|
+
method: "GET",
|
|
511
|
+
path: /^\/v4\/spreadsheets\/[A-Za-z0-9_-]+$/
|
|
512
|
+
},
|
|
513
|
+
"google.sheets.values.batchGet": {
|
|
514
|
+
access: "read",
|
|
515
|
+
host: GOOGLE_SHEETS_API_DOMAIN,
|
|
516
|
+
method: "GET",
|
|
517
|
+
path: /^\/v4\/spreadsheets\/[A-Za-z0-9_-]+\/values:batchGet$/
|
|
518
|
+
},
|
|
519
|
+
"google.slides.presentation.get": {
|
|
520
|
+
access: "read",
|
|
521
|
+
host: GOOGLE_SLIDES_API_DOMAIN,
|
|
522
|
+
method: "GET",
|
|
523
|
+
path: /^\/v1\/presentations\/[A-Za-z0-9_-]+$/
|
|
489
524
|
}
|
|
490
525
|
};
|
|
491
526
|
function googleGrantForEgress(ctx) {
|
|
@@ -497,7 +532,7 @@ function googleGrantForEgress(ctx) {
|
|
|
497
532
|
);
|
|
498
533
|
}
|
|
499
534
|
const url = new URL(ctx.request.url);
|
|
500
|
-
if (url.hostname !==
|
|
535
|
+
if (url.hostname !== rule.host || ctx.request.method.toUpperCase() !== rule.method || !rule.path.test(url.pathname)) {
|
|
501
536
|
throw new EgressPolicyDenied(
|
|
502
537
|
`Google request does not match operation ${operation}.`
|
|
503
538
|
);
|
|
@@ -547,12 +582,10 @@ async function issueGoogleCredential(ctx) {
|
|
|
547
582
|
lease: {
|
|
548
583
|
account: { id: config.accountEmail, label: config.accountEmail },
|
|
549
584
|
expiresAt: new Date(token.expiresAtMs - LEASE_SAFETY_MS).toISOString(),
|
|
550
|
-
headerTransforms:
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
}
|
|
555
|
-
]
|
|
585
|
+
headerTransforms: GOOGLE_API_DOMAINS.map((domain) => ({
|
|
586
|
+
domain,
|
|
587
|
+
headers: { Authorization: `Bearer ${token.accessToken}` }
|
|
588
|
+
}))
|
|
556
589
|
}
|
|
557
590
|
};
|
|
558
591
|
}
|
|
@@ -803,15 +836,18 @@ var googleErrorSchema = z2.object({
|
|
|
803
836
|
}).optional()
|
|
804
837
|
});
|
|
805
838
|
async function googleApiRequest(ctx, input) {
|
|
806
|
-
const
|
|
839
|
+
const rule = GOOGLE_OPERATIONS[input.operation];
|
|
840
|
+
const url = new URL(`https://${rule.host}${input.path}`);
|
|
807
841
|
for (const [key, value] of Object.entries(input.query ?? {})) {
|
|
808
|
-
|
|
842
|
+
for (const item of [value].flat()) {
|
|
843
|
+
url.searchParams.append(key, item);
|
|
844
|
+
}
|
|
809
845
|
}
|
|
810
846
|
const response = await ctx.egress.fetch({
|
|
811
847
|
operation: input.operation,
|
|
812
848
|
provider: "google",
|
|
813
849
|
request: new Request(url, {
|
|
814
|
-
method:
|
|
850
|
+
method: rule.method,
|
|
815
851
|
headers: {
|
|
816
852
|
Accept: "application/json",
|
|
817
853
|
"Content-Type": "application/json",
|
|
@@ -833,6 +869,11 @@ function googleApiError(operation, response) {
|
|
|
833
869
|
`Junior's Google account does not have the permission that ${operation} needs. A Junior admin must reconnect it on the dashboard Admin page or with \`junior google connect\`.`
|
|
834
870
|
);
|
|
835
871
|
}
|
|
872
|
+
if (response.status === 403 && error?.details?.some((detail2) => detail2.reason === "SERVICE_DISABLED")) {
|
|
873
|
+
return new Error(
|
|
874
|
+
`The Google API that ${operation} needs is not enabled for Junior's Google Cloud project. A Junior admin must enable it.`
|
|
875
|
+
);
|
|
876
|
+
}
|
|
836
877
|
const detail = error?.message;
|
|
837
878
|
const message = `Google ${operation} failed with HTTP ${response.status}${detail ? `: ${detail}` : ""}`;
|
|
838
879
|
return response.status === 400 ? new PluginToolInputError(message) : new Error(message);
|
|
@@ -1530,22 +1571,46 @@ function createFindMeetingTimesTool(ctx) {
|
|
|
1530
1571
|
});
|
|
1531
1572
|
}
|
|
1532
1573
|
|
|
1533
|
-
// src/tools/list-
|
|
1574
|
+
// src/tools/list-file-comments.ts
|
|
1534
1575
|
import {
|
|
1535
1576
|
definePluginTool as definePluginTool4,
|
|
1536
1577
|
pluginToolOutputSchema as pluginToolOutputSchema4
|
|
1537
1578
|
} from "@sentry/junior-plugin-api";
|
|
1538
1579
|
import { z as z7 } from "zod";
|
|
1539
1580
|
|
|
1540
|
-
// src/tools/
|
|
1581
|
+
// src/tools/files.ts
|
|
1541
1582
|
import { PluginToolInputError as PluginToolInputError4 } from "@sentry/junior-plugin-api";
|
|
1542
1583
|
import { z as z6 } from "zod";
|
|
1543
|
-
var
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1584
|
+
var FILE_TYPES = {
|
|
1585
|
+
document: {
|
|
1586
|
+
label: "Google Doc",
|
|
1587
|
+
mimeType: "application/vnd.google-apps.document"
|
|
1588
|
+
},
|
|
1589
|
+
presentation: {
|
|
1590
|
+
label: "Google Slides presentation",
|
|
1591
|
+
mimeType: "application/vnd.google-apps.presentation"
|
|
1592
|
+
},
|
|
1593
|
+
spreadsheet: {
|
|
1594
|
+
label: "Google Sheet",
|
|
1595
|
+
mimeType: "application/vnd.google-apps.spreadsheet"
|
|
1596
|
+
}
|
|
1597
|
+
};
|
|
1598
|
+
var GOOGLE_FILE_TYPES = Object.keys(FILE_TYPES);
|
|
1599
|
+
function googleFileMimeType(type) {
|
|
1600
|
+
return FILE_TYPES[type].mimeType;
|
|
1601
|
+
}
|
|
1602
|
+
function googleFileType(mimeType) {
|
|
1603
|
+
return GOOGLE_FILE_TYPES.find(
|
|
1604
|
+
(type) => FILE_TYPES[type].mimeType === mimeType
|
|
1605
|
+
);
|
|
1606
|
+
}
|
|
1607
|
+
function fileReferenceSchema(name) {
|
|
1608
|
+
return z6.string().trim().min(10).max(2048).describe(
|
|
1609
|
+
`${name} link, or a file id from searchGoogleFiles. Keep the full link for files shared by link: it can carry a resource key that Google needs.`
|
|
1610
|
+
);
|
|
1611
|
+
}
|
|
1547
1612
|
var FILE_ID_PATTERN = /^[A-Za-z0-9_-]{10,200}$/;
|
|
1548
|
-
function
|
|
1613
|
+
function parseFileReference(value) {
|
|
1549
1614
|
let fileId = value;
|
|
1550
1615
|
let resourceKey;
|
|
1551
1616
|
if (/^https?:\/\//.test(value)) {
|
|
@@ -1555,24 +1620,24 @@ function parseDocReference(value) {
|
|
|
1555
1620
|
}
|
|
1556
1621
|
if (!FILE_ID_PATTERN.test(fileId)) {
|
|
1557
1622
|
throw new PluginToolInputError4(
|
|
1558
|
-
"Use a Google Docs link or a
|
|
1623
|
+
"Use a Google Docs, Sheets, or Slides link, or a file id from searchGoogleFiles."
|
|
1559
1624
|
);
|
|
1560
1625
|
}
|
|
1561
1626
|
return { fileId, ...resourceKey ? { resourceKey } : void 0 };
|
|
1562
1627
|
}
|
|
1563
|
-
async function
|
|
1628
|
+
async function googleFileRequest(ctx, file, input) {
|
|
1564
1629
|
const response = await googleApiRequest(ctx, {
|
|
1565
1630
|
...input,
|
|
1566
1631
|
headers: {
|
|
1567
1632
|
...input.headers,
|
|
1568
|
-
...
|
|
1569
|
-
"X-Goog-Drive-Resource-Keys": `${
|
|
1633
|
+
...file.resourceKey ? {
|
|
1634
|
+
"X-Goog-Drive-Resource-Keys": `${file.fileId}/${file.resourceKey}`
|
|
1570
1635
|
} : void 0
|
|
1571
1636
|
}
|
|
1572
1637
|
});
|
|
1573
1638
|
if (response.status === 404) {
|
|
1574
1639
|
throw new PluginToolInputError4(
|
|
1575
|
-
`Junior's Google account (${ctx.accountEmail}) cannot open this
|
|
1640
|
+
`Junior's Google account (${ctx.accountEmail}) cannot open this file. Ask the owner to share it with that account, or to share it with anyone who has the link.`
|
|
1576
1641
|
);
|
|
1577
1642
|
}
|
|
1578
1643
|
if (response.status !== 200) {
|
|
@@ -1580,34 +1645,43 @@ async function driveFileRequest(ctx, doc, input) {
|
|
|
1580
1645
|
}
|
|
1581
1646
|
return response;
|
|
1582
1647
|
}
|
|
1583
|
-
var
|
|
1648
|
+
var driveFileSchema = z6.object({
|
|
1584
1649
|
id: z6.string(),
|
|
1585
1650
|
mimeType: z6.string(),
|
|
1586
1651
|
modifiedTime: z6.string().optional(),
|
|
1587
1652
|
name: z6.string(),
|
|
1588
1653
|
webViewLink: z6.string().optional()
|
|
1589
1654
|
});
|
|
1590
|
-
async function
|
|
1591
|
-
const response = await
|
|
1655
|
+
async function readGoogleFile(ctx, file, types) {
|
|
1656
|
+
const response = await googleFileRequest(ctx, file, {
|
|
1592
1657
|
operation: "google.drive.file.get",
|
|
1593
|
-
path: `/drive/v3/files/${
|
|
1658
|
+
path: `/drive/v3/files/${file.fileId}`,
|
|
1594
1659
|
query: {
|
|
1595
1660
|
fields: "id,mimeType,modifiedTime,name,webViewLink",
|
|
1596
1661
|
supportsAllDrives: "true"
|
|
1597
1662
|
}
|
|
1598
1663
|
});
|
|
1599
|
-
const
|
|
1600
|
-
|
|
1664
|
+
const metadata = driveFileSchema.parse(response.body);
|
|
1665
|
+
const type = googleFileType(metadata.mimeType);
|
|
1666
|
+
if (!type || !types.includes(type)) {
|
|
1667
|
+
const expected = types.map((item) => FILE_TYPES[item].label).join(" or ");
|
|
1601
1668
|
throw new PluginToolInputError4(
|
|
1602
|
-
`"${
|
|
1669
|
+
`"${metadata.name}" is not a ${expected} (${metadata.mimeType}).`
|
|
1603
1670
|
);
|
|
1604
1671
|
}
|
|
1605
|
-
return
|
|
1672
|
+
return { ...metadata, type };
|
|
1606
1673
|
}
|
|
1674
|
+
function fileOutputFields(file) {
|
|
1675
|
+
return {
|
|
1676
|
+
...file.modifiedTime ? { modifiedTime: file.modifiedTime } : void 0,
|
|
1677
|
+
...file.webViewLink ? { url: file.webViewLink } : void 0
|
|
1678
|
+
};
|
|
1679
|
+
}
|
|
1680
|
+
var MAX_CONTENT_CHARS = 1e5;
|
|
1607
1681
|
|
|
1608
|
-
// src/tools/list-
|
|
1682
|
+
// src/tools/list-file-comments.ts
|
|
1609
1683
|
var inputSchema4 = z7.object({
|
|
1610
|
-
|
|
1684
|
+
file: fileReferenceSchema("Google Docs, Sheets, or Slides"),
|
|
1611
1685
|
pageToken: z7.string().min(1).max(2048).optional().describe("nextPageToken from an earlier call, to read more comments.")
|
|
1612
1686
|
}).strict();
|
|
1613
1687
|
var replyOutputSchema = z7.object({
|
|
@@ -1621,15 +1695,15 @@ var commentOutputSchema = z7.object({
|
|
|
1621
1695
|
commentId: z7.string(),
|
|
1622
1696
|
content: z7.string(),
|
|
1623
1697
|
createdTime: z7.string().optional(),
|
|
1624
|
-
quotedText: z7.string().optional().describe("The
|
|
1698
|
+
quotedText: z7.string().optional().describe("The file text that the comment is attached to."),
|
|
1625
1699
|
replies: z7.array(replyOutputSchema),
|
|
1626
1700
|
resolved: z7.boolean()
|
|
1627
1701
|
});
|
|
1628
1702
|
var outputSchema4 = pluginToolOutputSchema4.extend({
|
|
1629
|
-
target: z7.literal("
|
|
1703
|
+
target: z7.literal("listGoogleFileComments"),
|
|
1630
1704
|
comments: z7.array(commentOutputSchema),
|
|
1631
|
-
|
|
1632
|
-
nextPageToken: z7.string().optional().describe("Set when the
|
|
1705
|
+
fileId: z7.string(),
|
|
1706
|
+
nextPageToken: z7.string().optional().describe("Set when the file has more comments. Pass it as pageToken.")
|
|
1633
1707
|
});
|
|
1634
1708
|
var authorSchema = z7.object({ displayName: z7.string().optional() }).optional();
|
|
1635
1709
|
var commentListSchema = z7.object({
|
|
@@ -1655,7 +1729,7 @@ var commentListSchema = z7.object({
|
|
|
1655
1729
|
nextPageToken: z7.string().optional()
|
|
1656
1730
|
});
|
|
1657
1731
|
var COMMENT_FIELDS = "comments(author/displayName,content,createdTime,id,quotedFileContent/value,resolved,replies(action,author/displayName,content,createdTime)),nextPageToken";
|
|
1658
|
-
function
|
|
1732
|
+
function createListGoogleFileCommentsTool(ctx) {
|
|
1659
1733
|
return definePluginTool4({
|
|
1660
1734
|
annotations: {
|
|
1661
1735
|
destructiveHint: false,
|
|
@@ -1663,15 +1737,15 @@ function createListGoogleDocCommentsTool(ctx) {
|
|
|
1663
1737
|
openWorldHint: true,
|
|
1664
1738
|
readOnlyHint: true
|
|
1665
1739
|
},
|
|
1666
|
-
description: "List the comments and replies on one Google Doc, as Junior's own Google account sees them. Each comment gives its author, text, the
|
|
1740
|
+
description: "List the comments and replies on one Google Doc, Sheet, or Slides presentation, as Junior's own Google account sees them. Each comment gives its author, text, the file text it is attached to, and whether it is resolved. Works for files shared with that account and files shared with anyone who has the link. Returns up to 100 comments per call; pass nextPageToken as pageToken to read more. Comments can be private: share only what the requester needs.",
|
|
1667
1741
|
inputSchema: inputSchema4,
|
|
1668
1742
|
outputSchema: outputSchema4,
|
|
1669
1743
|
async execute(input) {
|
|
1670
|
-
const
|
|
1671
|
-
await
|
|
1672
|
-
const response = await
|
|
1744
|
+
const ref = parseFileReference(input.file);
|
|
1745
|
+
await readGoogleFile(ctx, ref, GOOGLE_FILE_TYPES);
|
|
1746
|
+
const response = await googleFileRequest(ctx, ref, {
|
|
1673
1747
|
operation: "google.drive.comments.list",
|
|
1674
|
-
path: `/drive/v3/files/${
|
|
1748
|
+
path: `/drive/v3/files/${ref.fileId}/comments`,
|
|
1675
1749
|
query: {
|
|
1676
1750
|
fields: COMMENT_FIELDS,
|
|
1677
1751
|
pageSize: "100",
|
|
@@ -1682,7 +1756,7 @@ function createListGoogleDocCommentsTool(ctx) {
|
|
|
1682
1756
|
response.body
|
|
1683
1757
|
);
|
|
1684
1758
|
return {
|
|
1685
|
-
target: "
|
|
1759
|
+
target: "listGoogleFileComments",
|
|
1686
1760
|
comments: comments.map((comment) => ({
|
|
1687
1761
|
...comment.author?.displayName ? { author: comment.author.displayName } : void 0,
|
|
1688
1762
|
commentId: comment.id,
|
|
@@ -1697,7 +1771,7 @@ function createListGoogleDocCommentsTool(ctx) {
|
|
|
1697
1771
|
})),
|
|
1698
1772
|
resolved: comment.resolved === true
|
|
1699
1773
|
})),
|
|
1700
|
-
|
|
1774
|
+
fileId: ref.fileId,
|
|
1701
1775
|
...nextPageToken ? { nextPageToken } : void 0
|
|
1702
1776
|
};
|
|
1703
1777
|
}
|
|
@@ -1865,9 +1939,8 @@ import {
|
|
|
1865
1939
|
pluginToolOutputSchema as pluginToolOutputSchema6
|
|
1866
1940
|
} from "@sentry/junior-plugin-api";
|
|
1867
1941
|
import { z as z9 } from "zod";
|
|
1868
|
-
var MAX_CONTENT_CHARS = 1e5;
|
|
1869
1942
|
var inputSchema6 = z9.object({
|
|
1870
|
-
document:
|
|
1943
|
+
document: fileReferenceSchema("Google Docs")
|
|
1871
1944
|
}).strict();
|
|
1872
1945
|
var outputSchema6 = pluginToolOutputSchema6.extend({
|
|
1873
1946
|
target: z9.literal("readGoogleDoc"),
|
|
@@ -1888,16 +1961,16 @@ function createReadGoogleDocTool(ctx) {
|
|
|
1888
1961
|
openWorldHint: true,
|
|
1889
1962
|
readOnlyHint: true
|
|
1890
1963
|
},
|
|
1891
|
-
description: "Read the text of one Google Doc as Markdown, as Junior's own Google account sees it. Works for Docs shared with that account and Docs shared with anyone who has the link. Comments are not included; use
|
|
1964
|
+
description: "Read the text of one Google Doc as Markdown, as Junior's own Google account sees it. Works for Docs shared with that account and Docs shared with anyone who has the link. Comments are not included; use listGoogleFileComments for them. Doc contents can be private: share only what the requester needs, and avoid repeating them in public channels.",
|
|
1892
1965
|
inputSchema: inputSchema6,
|
|
1893
1966
|
outputSchema: outputSchema6,
|
|
1894
1967
|
async execute(input) {
|
|
1895
|
-
const
|
|
1896
|
-
const file = await
|
|
1897
|
-
const response = await
|
|
1968
|
+
const ref = parseFileReference(input.document);
|
|
1969
|
+
const file = await readGoogleFile(ctx, ref, ["document"]);
|
|
1970
|
+
const response = await googleFileRequest(ctx, ref, {
|
|
1898
1971
|
headers: { Accept: "text/markdown" },
|
|
1899
1972
|
operation: "google.drive.file.export",
|
|
1900
|
-
path: `/drive/v3/files/${
|
|
1973
|
+
path: `/drive/v3/files/${ref.fileId}/export`,
|
|
1901
1974
|
query: { mimeType: "text/markdown" }
|
|
1902
1975
|
});
|
|
1903
1976
|
const content = typeof response.body === "string" ? response.body : "";
|
|
@@ -1905,55 +1978,70 @@ function createReadGoogleDocTool(ctx) {
|
|
|
1905
1978
|
target: "readGoogleDoc",
|
|
1906
1979
|
content: content.slice(0, MAX_CONTENT_CHARS),
|
|
1907
1980
|
documentId: file.id,
|
|
1908
|
-
...file
|
|
1981
|
+
...fileOutputFields(file),
|
|
1909
1982
|
title: file.name,
|
|
1910
|
-
truncated: content.length > MAX_CONTENT_CHARS
|
|
1911
|
-
...file.webViewLink ? { url: file.webViewLink } : void 0
|
|
1983
|
+
truncated: content.length > MAX_CONTENT_CHARS
|
|
1912
1984
|
};
|
|
1913
1985
|
}
|
|
1914
1986
|
});
|
|
1915
1987
|
}
|
|
1916
1988
|
|
|
1917
|
-
// src/tools/
|
|
1989
|
+
// src/tools/read-sheet.ts
|
|
1918
1990
|
import {
|
|
1919
1991
|
definePluginTool as definePluginTool7,
|
|
1920
1992
|
pluginToolOutputSchema as pluginToolOutputSchema7
|
|
1921
1993
|
} from "@sentry/junior-plugin-api";
|
|
1922
1994
|
import { z as z10 } from "zod";
|
|
1923
1995
|
var inputSchema7 = z10.object({
|
|
1924
|
-
|
|
1925
|
-
|
|
1996
|
+
spreadsheet: fileReferenceSchema("Google Sheets"),
|
|
1997
|
+
range: z10.string().trim().min(1).max(500).optional().describe(
|
|
1998
|
+
"A1 range to read, such as 'Budget' for one tab or 'Budget!A1:F50'. Omit to read every tab."
|
|
1999
|
+
)
|
|
1926
2000
|
}).strict();
|
|
1927
2001
|
var outputSchema7 = pluginToolOutputSchema7.extend({
|
|
1928
|
-
target: z10.literal("
|
|
1929
|
-
|
|
2002
|
+
target: z10.literal("readGoogleSheet"),
|
|
2003
|
+
modifiedTime: z10.string().optional(),
|
|
2004
|
+
ranges: z10.array(
|
|
1930
2005
|
z10.object({
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
url: z10.string().optional()
|
|
2006
|
+
content: z10.string().describe("Cell values as CSV, as the Sheet shows them."),
|
|
2007
|
+
range: z10.string().describe("The A1 range that Google read."),
|
|
2008
|
+
truncated: z10.boolean().describe("True when rows at the end of this range are left out.")
|
|
1935
2009
|
})
|
|
1936
2010
|
),
|
|
2011
|
+
spreadsheetId: z10.string(),
|
|
2012
|
+
tabs: z10.array(z10.string()).describe("Names of every tab in the Sheet."),
|
|
2013
|
+
title: z10.string(),
|
|
1937
2014
|
truncated: z10.boolean().describe(
|
|
1938
|
-
|
|
1939
|
-
)
|
|
2015
|
+
`True when the cells are longer than ${MAX_CONTENT_CHARS} characters and some rows are left out. Pass a smaller range to read them.`
|
|
2016
|
+
),
|
|
2017
|
+
url: z10.string().optional()
|
|
1940
2018
|
});
|
|
1941
|
-
var
|
|
1942
|
-
|
|
2019
|
+
var spreadsheetSchema = z10.object({
|
|
2020
|
+
sheets: z10.array(
|
|
1943
2021
|
z10.object({
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
2022
|
+
properties: z10.object({
|
|
2023
|
+
sheetType: z10.string().optional(),
|
|
2024
|
+
title: z10.string()
|
|
2025
|
+
})
|
|
1948
2026
|
})
|
|
1949
|
-
).default([])
|
|
1950
|
-
incompleteSearch: z10.boolean().optional(),
|
|
1951
|
-
nextPageToken: z10.string().optional()
|
|
2027
|
+
).default([])
|
|
1952
2028
|
});
|
|
1953
|
-
|
|
1954
|
-
|
|
2029
|
+
var valuesSchema = z10.object({
|
|
2030
|
+
valueRanges: z10.array(
|
|
2031
|
+
z10.object({
|
|
2032
|
+
range: z10.string(),
|
|
2033
|
+
values: z10.array(z10.array(z10.unknown())).default([])
|
|
2034
|
+
})
|
|
2035
|
+
).default([])
|
|
2036
|
+
});
|
|
2037
|
+
function tabRange(title) {
|
|
2038
|
+
return `'${title.replace(/'/g, "''")}'`;
|
|
2039
|
+
}
|
|
2040
|
+
function csvCell(value) {
|
|
2041
|
+
const text2 = value === null || value === void 0 ? "" : String(value);
|
|
2042
|
+
return /[",\r\n]/.test(text2) ? `"${text2.replace(/"/g, '""')}"` : text2;
|
|
1955
2043
|
}
|
|
1956
|
-
function
|
|
2044
|
+
function createReadGoogleSheetTool(ctx) {
|
|
1957
2045
|
return definePluginTool7({
|
|
1958
2046
|
annotations: {
|
|
1959
2047
|
destructiveHint: false,
|
|
@@ -1961,19 +2049,251 @@ function createSearchGoogleDocsTool(ctx) {
|
|
|
1961
2049
|
openWorldHint: true,
|
|
1962
2050
|
readOnlyHint: true
|
|
1963
2051
|
},
|
|
1964
|
-
description: "
|
|
2052
|
+
description: "Read the cells of one Google Sheet as CSV, as Junior's own Google account sees it. Reads every tab, or one A1 range. Values are formatted as the Sheet shows them; formulas are not included. Works for Sheets shared with that account and Sheets shared with anyone who has the link. Comments are not included; use listGoogleFileComments for them. Sheet contents can be private: share only what the requester needs, and avoid repeating them in public channels.",
|
|
1965
2053
|
inputSchema: inputSchema7,
|
|
1966
2054
|
outputSchema: outputSchema7,
|
|
1967
2055
|
async execute(input) {
|
|
2056
|
+
const ref = parseFileReference(input.spreadsheet);
|
|
2057
|
+
const file = await readGoogleFile(ctx, ref, ["spreadsheet"]);
|
|
2058
|
+
const spreadsheet = await googleFileRequest(ctx, ref, {
|
|
2059
|
+
operation: "google.sheets.spreadsheet.get",
|
|
2060
|
+
path: `/v4/spreadsheets/${ref.fileId}`,
|
|
2061
|
+
query: { fields: "sheets.properties(sheetType,title)" }
|
|
2062
|
+
});
|
|
2063
|
+
const tabs = spreadsheetSchema.parse(spreadsheet.body).sheets.map((sheet) => sheet.properties).filter((tab) => (tab.sheetType ?? "GRID") === "GRID").map((tab) => tab.title);
|
|
2064
|
+
const values = await googleFileRequest(ctx, ref, {
|
|
2065
|
+
operation: "google.sheets.values.batchGet",
|
|
2066
|
+
path: `/v4/spreadsheets/${ref.fileId}/values:batchGet`,
|
|
2067
|
+
query: {
|
|
2068
|
+
majorDimension: "ROWS",
|
|
2069
|
+
ranges: input.range ? [input.range] : tabs.map(tabRange),
|
|
2070
|
+
valueRenderOption: "FORMATTED_VALUE"
|
|
2071
|
+
}
|
|
2072
|
+
});
|
|
2073
|
+
const { valueRanges } = valuesSchema.parse(values.body);
|
|
2074
|
+
let remaining = MAX_CONTENT_CHARS;
|
|
2075
|
+
const ranges = valueRanges.map(({ range, values: values2 }) => {
|
|
2076
|
+
const rows = [];
|
|
2077
|
+
for (const row of values2) {
|
|
2078
|
+
const line = row.map(csvCell).join(",");
|
|
2079
|
+
if (line.length + 1 > remaining) break;
|
|
2080
|
+
rows.push(line);
|
|
2081
|
+
remaining -= line.length + 1;
|
|
2082
|
+
}
|
|
2083
|
+
return {
|
|
2084
|
+
content: rows.join("\n"),
|
|
2085
|
+
range,
|
|
2086
|
+
truncated: rows.length < values2.length
|
|
2087
|
+
};
|
|
2088
|
+
});
|
|
2089
|
+
return {
|
|
2090
|
+
target: "readGoogleSheet",
|
|
2091
|
+
...fileOutputFields(file),
|
|
2092
|
+
ranges,
|
|
2093
|
+
spreadsheetId: file.id,
|
|
2094
|
+
tabs,
|
|
2095
|
+
title: file.name,
|
|
2096
|
+
truncated: ranges.some((range) => range.truncated)
|
|
2097
|
+
};
|
|
2098
|
+
}
|
|
2099
|
+
});
|
|
2100
|
+
}
|
|
2101
|
+
|
|
2102
|
+
// src/tools/read-slides.ts
|
|
2103
|
+
import {
|
|
2104
|
+
definePluginTool as definePluginTool8,
|
|
2105
|
+
pluginToolOutputSchema as pluginToolOutputSchema8
|
|
2106
|
+
} from "@sentry/junior-plugin-api";
|
|
2107
|
+
import { z as z11 } from "zod";
|
|
2108
|
+
var inputSchema8 = z11.object({
|
|
2109
|
+
presentation: fileReferenceSchema("Google Slides")
|
|
2110
|
+
}).strict();
|
|
2111
|
+
var outputSchema8 = pluginToolOutputSchema8.extend({
|
|
2112
|
+
target: z11.literal("readGoogleSlides"),
|
|
2113
|
+
modifiedTime: z11.string().optional(),
|
|
2114
|
+
presentationId: z11.string(),
|
|
2115
|
+
slideCount: z11.number().int(),
|
|
2116
|
+
slides: z11.array(
|
|
2117
|
+
z11.object({
|
|
2118
|
+
notes: z11.string().optional().describe("Speaker notes."),
|
|
2119
|
+
slideNumber: z11.number().int(),
|
|
2120
|
+
text: z11.string().describe("Text in the shapes and tables of the slide.")
|
|
2121
|
+
})
|
|
2122
|
+
),
|
|
2123
|
+
title: z11.string(),
|
|
2124
|
+
truncated: z11.boolean().describe(
|
|
2125
|
+
`True when the text is longer than ${MAX_CONTENT_CHARS} characters and the last slides are left out.`
|
|
2126
|
+
),
|
|
2127
|
+
url: z11.string().optional()
|
|
2128
|
+
});
|
|
2129
|
+
var textSchema = z11.object({
|
|
2130
|
+
textElements: z11.array(
|
|
2131
|
+
z11.object({
|
|
2132
|
+
textRun: z11.object({ content: z11.string().optional() }).optional()
|
|
2133
|
+
})
|
|
2134
|
+
).default([])
|
|
2135
|
+
}).optional();
|
|
2136
|
+
var pageElementSchema = z11.lazy(
|
|
2137
|
+
() => z11.object({
|
|
2138
|
+
elementGroup: z11.object({ children: z11.array(pageElementSchema).optional() }).optional(),
|
|
2139
|
+
objectId: z11.string().optional(),
|
|
2140
|
+
shape: z11.object({ text: textSchema }).optional(),
|
|
2141
|
+
table: z11.object({
|
|
2142
|
+
tableRows: z11.array(
|
|
2143
|
+
z11.object({
|
|
2144
|
+
tableCells: z11.array(z11.object({ text: textSchema })).optional()
|
|
2145
|
+
})
|
|
2146
|
+
).optional()
|
|
2147
|
+
}).optional()
|
|
2148
|
+
})
|
|
2149
|
+
);
|
|
2150
|
+
var presentationSchema = z11.object({
|
|
2151
|
+
slides: z11.array(
|
|
2152
|
+
z11.object({
|
|
2153
|
+
pageElements: z11.array(pageElementSchema).default([]),
|
|
2154
|
+
slideProperties: z11.object({
|
|
2155
|
+
notesPage: z11.object({
|
|
2156
|
+
notesProperties: z11.object({ speakerNotesObjectId: z11.string().optional() }).optional(),
|
|
2157
|
+
pageElements: z11.array(pageElementSchema).default([])
|
|
2158
|
+
}).optional()
|
|
2159
|
+
}).optional()
|
|
2160
|
+
})
|
|
2161
|
+
).default([])
|
|
2162
|
+
});
|
|
2163
|
+
function plainText(text2) {
|
|
2164
|
+
return (text2?.textElements ?? []).map((element) => element.textRun?.content ?? "").join("").trim();
|
|
2165
|
+
}
|
|
2166
|
+
function elementText(element) {
|
|
2167
|
+
if (element.shape) {
|
|
2168
|
+
return [plainText(element.shape.text)];
|
|
2169
|
+
}
|
|
2170
|
+
if (element.table) {
|
|
2171
|
+
return (element.table.tableRows ?? []).map(
|
|
2172
|
+
(row) => (row.tableCells ?? []).map((cell) => plainText(cell.text)).join(" | ")
|
|
2173
|
+
);
|
|
2174
|
+
}
|
|
2175
|
+
return (element.elementGroup?.children ?? []).flatMap(elementText);
|
|
2176
|
+
}
|
|
2177
|
+
function createReadGoogleSlidesTool(ctx) {
|
|
2178
|
+
return definePluginTool8({
|
|
2179
|
+
annotations: {
|
|
2180
|
+
destructiveHint: false,
|
|
2181
|
+
idempotentHint: true,
|
|
2182
|
+
openWorldHint: true,
|
|
2183
|
+
readOnlyHint: true
|
|
2184
|
+
},
|
|
2185
|
+
description: "Read the text and speaker notes of each slide in one Google Slides presentation, as Junior's own Google account sees it. Images and charts are not described. Works for presentations shared with that account and presentations shared with anyone who has the link. Comments are not included; use listGoogleFileComments for them. Slide contents can be private: share only what the requester needs, and avoid repeating them in public channels.",
|
|
2186
|
+
inputSchema: inputSchema8,
|
|
2187
|
+
outputSchema: outputSchema8,
|
|
2188
|
+
async execute(input) {
|
|
2189
|
+
const ref = parseFileReference(input.presentation);
|
|
2190
|
+
const file = await readGoogleFile(ctx, ref, ["presentation"]);
|
|
2191
|
+
const response = await googleFileRequest(ctx, ref, {
|
|
2192
|
+
operation: "google.slides.presentation.get",
|
|
2193
|
+
path: `/v1/presentations/${ref.fileId}`,
|
|
2194
|
+
query: {
|
|
2195
|
+
fields: "slides(pageElements,slideProperties/notesPage(notesProperties,pageElements))"
|
|
2196
|
+
}
|
|
2197
|
+
});
|
|
2198
|
+
const presentation = presentationSchema.parse(response.body);
|
|
2199
|
+
let remaining = MAX_CONTENT_CHARS;
|
|
2200
|
+
const slides = [];
|
|
2201
|
+
for (const [index, slide] of presentation.slides.entries()) {
|
|
2202
|
+
const text2 = slide.pageElements.flatMap(elementText).filter(Boolean).join("\n");
|
|
2203
|
+
const notesPage = slide.slideProperties?.notesPage;
|
|
2204
|
+
const notesId = notesPage?.notesProperties?.speakerNotesObjectId;
|
|
2205
|
+
const notesElement = notesId ? notesPage?.pageElements.find(
|
|
2206
|
+
(element) => element.objectId === notesId
|
|
2207
|
+
) : void 0;
|
|
2208
|
+
const notes = notesElement ? elementText(notesElement).join("\n") : "";
|
|
2209
|
+
const size = text2.length + notes.length;
|
|
2210
|
+
if (size > remaining) break;
|
|
2211
|
+
remaining -= size;
|
|
2212
|
+
slides.push({
|
|
2213
|
+
...notes ? { notes } : void 0,
|
|
2214
|
+
slideNumber: index + 1,
|
|
2215
|
+
text: text2
|
|
2216
|
+
});
|
|
2217
|
+
}
|
|
2218
|
+
return {
|
|
2219
|
+
target: "readGoogleSlides",
|
|
2220
|
+
...fileOutputFields(file),
|
|
2221
|
+
presentationId: file.id,
|
|
2222
|
+
slideCount: presentation.slides.length,
|
|
2223
|
+
slides,
|
|
2224
|
+
title: file.name,
|
|
2225
|
+
truncated: slides.length < presentation.slides.length
|
|
2226
|
+
};
|
|
2227
|
+
}
|
|
2228
|
+
});
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2231
|
+
// src/tools/search-files.ts
|
|
2232
|
+
import {
|
|
2233
|
+
definePluginTool as definePluginTool9,
|
|
2234
|
+
pluginToolOutputSchema as pluginToolOutputSchema9
|
|
2235
|
+
} from "@sentry/junior-plugin-api";
|
|
2236
|
+
import { z as z12 } from "zod";
|
|
2237
|
+
var inputSchema9 = z12.object({
|
|
2238
|
+
query: z12.string().trim().min(1).max(500).describe("Words to find in the file title or text."),
|
|
2239
|
+
types: z12.array(z12.enum(GOOGLE_FILE_TYPES)).min(1).optional().describe(
|
|
2240
|
+
"File types to find: document (Docs), spreadsheet (Sheets), presentation (Slides). Omit to find all three."
|
|
2241
|
+
),
|
|
2242
|
+
maxResults: z12.number().int().min(1).max(50).default(10)
|
|
2243
|
+
}).strict();
|
|
2244
|
+
var outputSchema9 = pluginToolOutputSchema9.extend({
|
|
2245
|
+
target: z12.literal("searchGoogleFiles"),
|
|
2246
|
+
files: z12.array(
|
|
2247
|
+
z12.object({
|
|
2248
|
+
fileId: z12.string(),
|
|
2249
|
+
modifiedTime: z12.string().optional(),
|
|
2250
|
+
title: z12.string(),
|
|
2251
|
+
type: z12.enum(GOOGLE_FILE_TYPES),
|
|
2252
|
+
url: z12.string().optional()
|
|
2253
|
+
})
|
|
2254
|
+
),
|
|
2255
|
+
truncated: z12.boolean().describe(
|
|
2256
|
+
"True when more files match, or Google did not search every Drive."
|
|
2257
|
+
)
|
|
2258
|
+
});
|
|
2259
|
+
var fileListSchema = z12.object({
|
|
2260
|
+
files: z12.array(
|
|
2261
|
+
z12.object({
|
|
2262
|
+
id: z12.string(),
|
|
2263
|
+
mimeType: z12.string(),
|
|
2264
|
+
modifiedTime: z12.string().optional(),
|
|
2265
|
+
name: z12.string(),
|
|
2266
|
+
webViewLink: z12.string().optional()
|
|
2267
|
+
})
|
|
2268
|
+
).default([]),
|
|
2269
|
+
incompleteSearch: z12.boolean().optional(),
|
|
2270
|
+
nextPageToken: z12.string().optional()
|
|
2271
|
+
});
|
|
2272
|
+
function driveQueryString(value) {
|
|
2273
|
+
return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
2274
|
+
}
|
|
2275
|
+
function createSearchGoogleFilesTool(ctx) {
|
|
2276
|
+
return definePluginTool9({
|
|
2277
|
+
annotations: {
|
|
2278
|
+
destructiveHint: false,
|
|
2279
|
+
idempotentHint: true,
|
|
2280
|
+
openWorldHint: true,
|
|
2281
|
+
readOnlyHint: true
|
|
2282
|
+
},
|
|
2283
|
+
description: "Find Google Docs, Sheets, and Slides shared with Junior's own Google account, by words in the title or text. Files that are only shared by public link are not found; ask for their link instead. Returns file ids for readGoogleDoc, readGoogleSheet, readGoogleSlides, and listGoogleFileComments.",
|
|
2284
|
+
inputSchema: inputSchema9,
|
|
2285
|
+
outputSchema: outputSchema9,
|
|
2286
|
+
async execute(input) {
|
|
2287
|
+
const mimeTypes = (input.types ?? GOOGLE_FILE_TYPES).map((type) => `mimeType = '${googleFileMimeType(type)}'`).join(" or ");
|
|
1968
2288
|
const response = await googleApiRequest(ctx, {
|
|
1969
2289
|
operation: "google.drive.files.list",
|
|
1970
2290
|
path: "/drive/v3/files",
|
|
1971
2291
|
query: {
|
|
1972
2292
|
corpora: "allDrives",
|
|
1973
|
-
fields: "files(id,modifiedTime,name,webViewLink),incompleteSearch,nextPageToken",
|
|
2293
|
+
fields: "files(id,mimeType,modifiedTime,name,webViewLink),incompleteSearch,nextPageToken",
|
|
1974
2294
|
includeItemsFromAllDrives: "true",
|
|
1975
2295
|
pageSize: String(input.maxResults),
|
|
1976
|
-
q: `
|
|
2296
|
+
q: `(${mimeTypes}) and trashed = false and fullText contains ${driveQueryString(input.query)}`,
|
|
1977
2297
|
supportsAllDrives: "true"
|
|
1978
2298
|
}
|
|
1979
2299
|
});
|
|
@@ -1984,13 +2304,18 @@ function createSearchGoogleDocsTool(ctx) {
|
|
|
1984
2304
|
response.body
|
|
1985
2305
|
);
|
|
1986
2306
|
return {
|
|
1987
|
-
target: "
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
2307
|
+
target: "searchGoogleFiles",
|
|
2308
|
+
files: files.flatMap((file) => {
|
|
2309
|
+
const type = googleFileType(file.mimeType);
|
|
2310
|
+
return type ? [
|
|
2311
|
+
{
|
|
2312
|
+
fileId: file.id,
|
|
2313
|
+
...fileOutputFields(file),
|
|
2314
|
+
title: file.name,
|
|
2315
|
+
type
|
|
2316
|
+
}
|
|
2317
|
+
] : [];
|
|
2318
|
+
}),
|
|
1994
2319
|
truncated: nextPageToken !== void 0 || incompleteSearch === true
|
|
1995
2320
|
};
|
|
1996
2321
|
}
|
|
@@ -1999,27 +2324,27 @@ function createSearchGoogleDocsTool(ctx) {
|
|
|
1999
2324
|
|
|
2000
2325
|
// src/tools/update-event.ts
|
|
2001
2326
|
import {
|
|
2002
|
-
definePluginTool as
|
|
2327
|
+
definePluginTool as definePluginTool10,
|
|
2003
2328
|
PluginToolInputError as PluginToolInputError6,
|
|
2004
|
-
pluginToolOutputSchema as
|
|
2329
|
+
pluginToolOutputSchema as pluginToolOutputSchema10
|
|
2005
2330
|
} from "@sentry/junior-plugin-api";
|
|
2006
|
-
import { z as
|
|
2007
|
-
var
|
|
2331
|
+
import { z as z13 } from "zod";
|
|
2332
|
+
var inputSchema10 = z13.object({
|
|
2008
2333
|
eventId: ownEventIdSchema,
|
|
2009
|
-
title:
|
|
2010
|
-
description:
|
|
2334
|
+
title: z13.string().trim().min(1).max(200).optional(),
|
|
2335
|
+
description: z13.string().max(4e3).optional().describe(
|
|
2011
2336
|
"Replacement description. Do not include private details the attendees should not see."
|
|
2012
2337
|
),
|
|
2013
|
-
start:
|
|
2014
|
-
end:
|
|
2338
|
+
start: z13.iso.datetime({ offset: true }).optional().describe("New start, RFC 3339 with offset. Give end too."),
|
|
2339
|
+
end: z13.iso.datetime({ offset: true }).optional().describe("New end, RFC 3339 with offset. Give start too."),
|
|
2015
2340
|
timeZone: timeZoneSchema,
|
|
2016
|
-
location:
|
|
2341
|
+
location: z13.string().trim().max(500).optional().describe(
|
|
2017
2342
|
"Replacement location, such as a room name or address. Use an empty string to clear it."
|
|
2018
2343
|
),
|
|
2019
2344
|
addAttendees: emailListSchema(50).default([]).describe("Email addresses to invite as required attendees."),
|
|
2020
2345
|
addOptionalAttendees: emailListSchema(50).default([]).describe("Email addresses to invite as optional attendees."),
|
|
2021
2346
|
removeAttendees: emailListSchema(50).default([]).describe("Email addresses to remove from the event."),
|
|
2022
|
-
addVideoCall:
|
|
2347
|
+
addVideoCall: z13.literal(true).optional().describe("Add a Google Meet link when the event has none.")
|
|
2023
2348
|
}).strict().refine(
|
|
2024
2349
|
(input) => input.start === void 0 === (input.end === void 0),
|
|
2025
2350
|
{
|
|
@@ -2029,12 +2354,12 @@ var inputSchema8 = z11.object({
|
|
|
2029
2354
|
(input) => input.title !== void 0 || input.description !== void 0 || input.start !== void 0 || input.location !== void 0 || input.addVideoCall !== void 0 || input.addAttendees.length > 0 || input.addOptionalAttendees.length > 0 || input.removeAttendees.length > 0,
|
|
2030
2355
|
{ message: "Give at least one change." }
|
|
2031
2356
|
);
|
|
2032
|
-
var
|
|
2033
|
-
target:
|
|
2357
|
+
var outputSchema10 = pluginToolOutputSchema10.extend({
|
|
2358
|
+
target: z13.literal("updateCalendarEvent"),
|
|
2034
2359
|
...ownEventOutputFields
|
|
2035
2360
|
});
|
|
2036
2361
|
function createUpdateCalendarEventTool(ctx) {
|
|
2037
|
-
return
|
|
2362
|
+
return definePluginTool10({
|
|
2038
2363
|
annotations: {
|
|
2039
2364
|
destructiveHint: false,
|
|
2040
2365
|
idempotentHint: true,
|
|
@@ -2055,8 +2380,8 @@ function createUpdateCalendarEventTool(ctx) {
|
|
|
2055
2380
|
return `Update Google Calendar event ${input.eventId}: ${changes.join("; ")}. Attendees get an email about the change.`;
|
|
2056
2381
|
},
|
|
2057
2382
|
description: "Change a Google Calendar event organized by Junior's own Google account: title, description, time, location, video call, or attendees. Use it to reschedule, add or remove people, or fix details. Google emails the attendees about the change, and existing attendees keep their responses. Only people invited to the event can ask for changes, and only people in the company's Google Workspace domains can be invited. Junior cannot change events other people organize. For a repeating event, an occurrence id changes only that occurrence; its seriesEventId changes every occurrence. Confirm the change with the requester first unless they already stated it exactly.",
|
|
2058
|
-
inputSchema:
|
|
2059
|
-
outputSchema:
|
|
2383
|
+
inputSchema: inputSchema10,
|
|
2384
|
+
outputSchema: outputSchema10,
|
|
2060
2385
|
async execute(input) {
|
|
2061
2386
|
const timeZone = input.timeZone ?? await ctx.users.resolveTimezone();
|
|
2062
2387
|
if (input.start && input.end) {
|
|
@@ -2147,8 +2472,8 @@ function googlePlugin() {
|
|
|
2147
2472
|
manifest: {
|
|
2148
2473
|
name: "google",
|
|
2149
2474
|
displayName: "Google Workspace",
|
|
2150
|
-
description: "Google Calendar scheduling and Google Docs reading as Junior's own Google Workspace account",
|
|
2151
|
-
domains:
|
|
2475
|
+
description: "Google Calendar scheduling and Google Docs, Sheets, and Slides reading as Junior's own Google Workspace account",
|
|
2476
|
+
domains: GOOGLE_API_DOMAINS,
|
|
2152
2477
|
envVars: {
|
|
2153
2478
|
[GOOGLE_CLIENT_ID_ENV]: {},
|
|
2154
2479
|
[GOOGLE_CLIENT_SECRET_ENV]: {},
|
|
@@ -2183,9 +2508,11 @@ function googlePlugin() {
|
|
|
2183
2508
|
createCalendarEvent: createCreateCalendarEventTool(toolContext),
|
|
2184
2509
|
findMeetingTimes: createFindMeetingTimesTool(toolContext),
|
|
2185
2510
|
listCalendarEvents: createListCalendarEventsTool(toolContext),
|
|
2186
|
-
|
|
2511
|
+
listGoogleFileComments: createListGoogleFileCommentsTool(toolContext),
|
|
2187
2512
|
readGoogleDoc: createReadGoogleDocTool(toolContext),
|
|
2188
|
-
|
|
2513
|
+
readGoogleSheet: createReadGoogleSheetTool(toolContext),
|
|
2514
|
+
readGoogleSlides: createReadGoogleSlidesTool(toolContext),
|
|
2515
|
+
searchGoogleFiles: createSearchGoogleFilesTool(toolContext),
|
|
2189
2516
|
updateCalendarEvent: createUpdateCalendarEventTool(toolContext)
|
|
2190
2517
|
};
|
|
2191
2518
|
}
|