@sentry/junior-google 0.268.0 → 0.269.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 +20 -198
- package/dist/tools/read-meeting-transcript.d.ts +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,207 +1,29 @@
|
|
|
1
1
|
# @sentry/junior-google
|
|
2
2
|
|
|
3
|
-
Proof of concept. Junior
|
|
4
|
-
`junior@
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
This version supports Calendar, Meet transcripts, and reading Google Docs,
|
|
8
|
-
Sheets, and Slides.
|
|
9
|
-
Gmail and Drive writes are out of scope.
|
|
10
|
-
|
|
11
|
-
## Surfaces
|
|
12
|
-
|
|
13
|
-
- `findMeetingTimes` finds times when every required attendee is free and
|
|
14
|
-
inside working hours (09:00 to 17:00 by default) in the time zone of their
|
|
15
|
-
own calendar. It reads free/busy data and calendar time zones only. It never
|
|
16
|
-
reads event titles or details. Optional attendees do not block a slot.
|
|
17
|
-
Slots where they are free come first, and each slot names the optional
|
|
18
|
-
attendees who are busy or off hours. A search can be limited to some
|
|
19
|
-
weekdays, such as Wednesdays and Fridays for a weekly meeting. A search
|
|
20
|
-
covers at most 14 days, counted on the local clock, so a daylight-saving
|
|
21
|
-
change does not shorten it. Slots are spread across days and across each
|
|
22
|
-
day, so the requester gets a real choice.
|
|
23
|
-
- Every Calendar tool takes an optional `timeZone` for the times it reads and
|
|
24
|
-
shows. Without it, the tool uses the requester's timezone from
|
|
25
|
-
`ctx.users.resolveTimezone()`, so Junior does not have to ask for one.
|
|
26
|
-
- `createCalendarEvent` creates an event on Junior's own calendar. It sends
|
|
27
|
-
invites and always adds a Google Meet link. It can add a location, optional
|
|
28
|
-
attendees, and a simple repeat rule (weekdays, weekly, or monthly). A retry of the same
|
|
29
|
-
tool call returns the same event. It does not create a second invite.
|
|
30
|
-
- `listCalendarEvents` reads the events on one colleague's calendar, or on
|
|
31
|
-
Junior's own calendar when no calendar is given. It shows only what the
|
|
32
|
-
calendar's Google sharing settings let Junior's account see. A calendar
|
|
33
|
-
shared as free/busy only shows busy blocks without titles. It never returns
|
|
34
|
-
event descriptions. Each event says whether Junior organizes it, and gives
|
|
35
|
-
attendee responses and the series id of a repeating event.
|
|
36
|
-
- `updateCalendarEvent` and `cancelCalendarEvent` accept an event id or a
|
|
37
|
-
Google Calendar event link.
|
|
38
|
-
- `updateCalendarEvent` changes the title, description, time, location, video
|
|
39
|
-
call, or attendees of an event that Junior organizes. Google emails the
|
|
40
|
-
attendees about the change. Only people invited to the event can ask for a
|
|
41
|
-
change.
|
|
42
|
-
- `cancelCalendarEvent` deletes an event that Junior organizes. Google removes
|
|
43
|
-
it from every attendee's calendar and emails them a cancellation. Only
|
|
44
|
-
people invited to the event can ask to cancel it.
|
|
45
|
-
- `createCalendarEvent` and `updateCalendarEvent` save a Calendar event
|
|
46
|
-
annotation on the Conversation. Junior shows its card with the next reply.
|
|
47
|
-
The card shows the title, time, and attendees, and links to the event. A
|
|
48
|
-
change to an event replaces its card.
|
|
49
|
-
- `searchGoogleFiles` finds Google Docs, Sheets, and Slides that are shared
|
|
50
|
-
with Junior's account, by words in the title or text. A search can ask for only
|
|
51
|
-
some of these types. Files that are only shared by public link are not found,
|
|
52
|
-
because Drive search only covers files the account has.
|
|
53
|
-
- The read tools take a link or a file id. They work for files shared with
|
|
54
|
-
Junior's account and for files shared with anyone who has the link. A link's
|
|
55
|
-
`resourcekey` value is sent to Google, because older files shared by link
|
|
56
|
-
need it. Each result stops at 100,000 characters.
|
|
57
|
-
- `readGoogleDoc` reads one Doc as Markdown. Drive exports the Doc, so the
|
|
58
|
-
Docs API is not used.
|
|
59
|
-
- `readGoogleSheet` reads the cells of one Sheet as CSV, with values formatted
|
|
60
|
-
as the Sheet shows them. It reads every tab, or one A1 range such as
|
|
61
|
-
`Budget!A1:F50`. The result names every tab, so Junior can ask for a smaller
|
|
62
|
-
range when a Sheet is too large. A Drive CSV export has only the first tab,
|
|
63
|
-
so this tool uses the Sheets API.
|
|
64
|
-
- `readGoogleSlides` reads the text and speaker notes of each slide, with
|
|
65
|
-
tables as `|` rows. It uses the Slides API to keep slide numbers and notes.
|
|
66
|
-
- `listGoogleFileComments` reads the comments and replies on one Doc, Sheet,
|
|
67
|
-
or Slides file, 100 per call. Each comment gives its author name, text, the
|
|
68
|
-
file text it is attached to, and whether it is resolved.
|
|
69
|
-
- `readMeetingTranscript` reads the Meet transcript and Gemini notes of one
|
|
70
|
-
meeting on Junior's calendar. Junior and the requester must both be invited
|
|
71
|
-
to the meeting. Junior does not have to join the call. When someone turns on
|
|
72
|
-
transcription or Gemini notes, Google saves them as Docs in the organizer's
|
|
73
|
-
Drive, attaches them to the Calendar event, and shares them with every
|
|
74
|
-
invitee in the organizer's domain. The tool reads these Docs from the event
|
|
75
|
-
attachments, so it needs no Meet scope. It reads an attached Doc only when
|
|
76
|
-
the organizer owns it and it was made after the meeting started. Thus a Doc
|
|
77
|
-
that someone else attaches to the event, or an agenda made before the
|
|
78
|
-
meeting, is not read. It does not require a title format, because Meet can
|
|
79
|
-
change the titles and they differ by language. The title only sets `kind`.
|
|
80
|
-
Google can take from some minutes to a few hours after the call to attach
|
|
81
|
-
the records, so an automation must allow for this delay. The result marks
|
|
82
|
-
the text as untrusted. The tool only reads. Junior acts on what was said
|
|
83
|
-
only when the requester or an automation asks for it.
|
|
84
|
-
- A transcript of a long meeting can be megabytes. The result returns at
|
|
85
|
-
most 100,000 characters inline. The tool saves the full text of each cut
|
|
86
|
-
record to a Markdown file in the Conversation sandbox, under `meetings/`,
|
|
87
|
-
and returns its `path`. Junior then reads or searches the full file in
|
|
88
|
-
parts. Drive cannot export a Doc larger than 10 MB.
|
|
89
|
-
- The **Google account** page on the dashboard Admin page shows whether the
|
|
90
|
-
account is connected. Its Connect button starts Google sign-in.
|
|
91
|
-
- `junior google connect` and `junior google status` are the operator CLI.
|
|
92
|
-
|
|
93
|
-
## Authentication
|
|
94
|
-
|
|
95
|
-
A Junior admin connects the account one time, out of band. Slack never shows
|
|
96
|
-
the sign-in link, the authorization code, or any token. Junior admins are
|
|
97
|
-
managed with `junior admin grant <email>`. This plugin has no admin list of its
|
|
98
|
-
own.
|
|
99
|
-
|
|
100
|
-
1. An admin opens **Admin → Google account** in the dashboard and selects
|
|
101
|
-
**Connect**, or runs `junior google connect`.
|
|
102
|
-
2. Google sign-in opens with PKCE and a single-use state value.
|
|
103
|
-
3. The admin signs in as the configured account, not as themselves.
|
|
104
|
-
4. Junior checks that the identity token names the configured account. It also
|
|
105
|
-
checks that Google granted every Calendar and Drive scope. If a check
|
|
106
|
-
fails, Junior revokes the grant and stores nothing.
|
|
107
|
-
5. Junior stores the refresh token in the `junior_google_accounts` table.
|
|
108
|
-
|
|
109
|
-
At runtime, the `issueCredential` hook exchanges the refresh token for a
|
|
110
|
-
one-hour access token. Junior applies that token only to `www.googleapis.com`
|
|
111
|
-
requests from this plugin's tools. The `grantForEgress` hook denies sandbox
|
|
112
|
-
commands and any request that does not match a declared operation. Thus the
|
|
113
|
-
model cannot use `curl` to read Junior's calendar or Drive and skip the tool
|
|
114
|
-
rules.
|
|
115
|
-
|
|
116
|
-
If Google rejects the refresh token (`invalid_grant`), Junior deletes it. The
|
|
117
|
-
tools then report that an admin must connect the account again. If the stored
|
|
118
|
-
grant does not have every scope the current tools need, Google rejects the
|
|
119
|
-
request and the tool asks an admin to reconnect.
|
|
120
|
-
|
|
121
|
-
## Rules in code
|
|
122
|
-
|
|
123
|
-
- Junior checks and invites only people in the allowed domains. By default,
|
|
124
|
-
the allowed domain is the domain of the account email.
|
|
125
|
-
- Junior adds the requester to the attendees when it knows their email.
|
|
126
|
-
- Junior changes or cancels only events that it organizes, and only for a
|
|
127
|
-
requester who is invited to the event. The `calendar.events.owned` scope
|
|
128
|
-
also keeps events that other people organize out of reach.
|
|
129
|
-
- Calendar scopes are `calendar.events.freebusy`, `calendar.events.readonly`,
|
|
130
|
-
and `calendar.events.owned`.
|
|
131
|
-
- The Drive scope is `drive.readonly`. The Drive comments API accepts no
|
|
132
|
-
narrower read scope, and the Sheets and Slides APIs also accept it. Junior
|
|
133
|
-
permits only these requests: Drive file search, file metadata, export, and
|
|
134
|
-
comment reads; Sheets metadata and cell reads; and Slides reads. Each
|
|
135
|
-
request must go to the host of its own API.
|
|
136
|
-
- Junior also requests `openid email` to verify the account during sign-in.
|
|
137
|
-
- Drive sharing decides which files Junior can read. The file tools read
|
|
138
|
-
any Doc, Sheet, or Slides file shared with Junior's account. This includes
|
|
139
|
-
Meet transcripts and Gemini notes, which Google shares with Junior when it
|
|
140
|
-
is invited. `readMeetingTranscript` finds the records from the Calendar
|
|
141
|
-
event and adds the invite checks. It is not the only way to read them.
|
|
3
|
+
Proof of concept. Junior uses its own Google Workspace account, such as
|
|
4
|
+
`junior@example.com`, to schedule meetings, read Meet transcripts, and read
|
|
5
|
+
Google Docs, Sheets, and Slides that are shared with that account. Junior does
|
|
6
|
+
not use the Google credentials of the people it helps.
|
|
142
7
|
|
|
143
8
|
## Setup
|
|
144
9
|
|
|
145
|
-
The plugin uses the same Google OAuth client as dashboard sign-in. Each
|
|
146
|
-
sign-in requests only its own scopes, so dashboard sign-in still asks only for
|
|
147
|
-
identity.
|
|
148
|
-
|
|
149
10
|
1. In the Google Cloud project of the dashboard OAuth client, enable the
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
- `https://<junior host>/api/plugins/google/oauth/callback`
|
|
158
|
-
- `http://127.0.0.1:8765/oauth/callback`, for the CLI. Use another port with
|
|
159
|
-
`junior google connect --port`.
|
|
11
|
+
Calendar, Drive, Sheets, and Slides APIs.
|
|
12
|
+
2. Use an **Internal** consent screen. Add the scopes
|
|
13
|
+
`calendar.events.freebusy`, `calendar.events.readonly`,
|
|
14
|
+
`calendar.events.owned`, and `drive.readonly`.
|
|
15
|
+
3. Add the redirect URIs
|
|
16
|
+
`https://<junior host>/api/plugins/google/oauth/callback` and
|
|
17
|
+
`http://127.0.0.1:8765/oauth/callback` (CLI).
|
|
160
18
|
4. Give the Junior account a Workspace license.
|
|
161
|
-
5. Set
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
| `GOOGLE_WORKSPACE_ACCOUNT_EMAIL` | The account Junior acts as |
|
|
168
|
-
| `GOOGLE_WORKSPACE_ALLOWED_DOMAINS` | Optional comma-separated domains to schedule in |
|
|
169
|
-
|
|
170
|
-
The plugin registers no tools and no sign-in routes until the first three
|
|
171
|
-
variables are set. The Admin page shows **Not configured** until then.
|
|
172
|
-
|
|
173
|
-
6. Run `junior upgrade` to create the table.
|
|
174
|
-
7. Run `junior admin grant <email>` for each person who may connect the account.
|
|
175
|
-
8. Connect the account on **Admin → Google account**, or run
|
|
176
|
-
`junior google connect` with the deployment database configured.
|
|
19
|
+
5. Set `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`,
|
|
20
|
+
`GOOGLE_WORKSPACE_ACCOUNT_EMAIL`, and optionally
|
|
21
|
+
`GOOGLE_WORKSPACE_ALLOWED_DOMAINS`.
|
|
22
|
+
6. Run `junior upgrade`, then `junior admin grant <email>` for each admin.
|
|
23
|
+
7. Connect the account on **Admin → Google account** in the dashboard, or run
|
|
24
|
+
`junior google connect`.
|
|
177
25
|
|
|
178
|
-
|
|
26
|
+
Anyone who can talk to Junior can read what the Junior account can see. Share
|
|
27
|
+
calendars and files with that account only when that is acceptable.
|
|
179
28
|
|
|
180
|
-
|
|
181
|
-
tracked in getsentry/junior#2065.
|
|
182
|
-
- Free/busy and event details show only what the company's calendar sharing
|
|
183
|
-
default allows. Calendars that Junior cannot see appear in `unavailable`
|
|
184
|
-
for `findMeetingTimes`, and as `visible: false` for `listCalendarEvents`.
|
|
185
|
-
- Anyone who can talk to Junior can ask it to read a colleague's calendar.
|
|
186
|
-
Junior returns what its own account can see, so set the sharing default
|
|
187
|
-
with that in mind.
|
|
188
|
-
- Anyone who can talk to Junior can also ask it to read any file shared with
|
|
189
|
-
Junior's account. Share a file with that account only when everyone who can
|
|
190
|
-
talk to Junior may read it.
|
|
191
|
-
- `drive.readonly` lets the account read every Drive file it can open. The
|
|
192
|
-
tools read only Google Docs, Sheets, and Slides.
|
|
193
|
-
- `readGoogleSheet` does not return formulas, notes on cells, or charts.
|
|
194
|
-
`readGoogleSlides` does not describe images or charts.
|
|
195
|
-
- Google does not expose the working hours that people set in Calendar.
|
|
196
|
-
Junior uses each calendar's time zone and one shared workday instead.
|
|
197
|
-
- Junior cannot find or book meeting rooms. Room discovery needs the Admin
|
|
198
|
-
SDK `admin.directory.resource.calendar.readonly` scope and a Workspace
|
|
199
|
-
admin role on Junior's account. Room emails are also outside the allowed
|
|
200
|
-
domains. It cannot accept or decline invites for other people.
|
|
201
|
-
- Google does not share Meet records with invitees when more than 200 people
|
|
202
|
-
in the organizer's domain are invited.
|
|
203
|
-
- Junior reads a transcript only when someone asks. No event tells
|
|
204
|
-
automations that a transcript is ready yet. Tracking issue:
|
|
205
|
-
getsentry/junior#2100.
|
|
206
|
-
- No disconnect command. To revoke access, remove the app grant from the
|
|
207
|
-
Junior account in Google.
|
|
29
|
+
Plugin setup: https://junior.sentry.dev/extend/
|
|
@@ -5,7 +5,7 @@ import { type GoogleToolContext } from "./shared";
|
|
|
5
5
|
*
|
|
6
6
|
* Anyone who can edit an event can attach any Doc, so the tool reads only
|
|
7
7
|
* attached Docs that the organizer owns and that were made for this meeting.
|
|
8
|
-
* The package
|
|
8
|
+
* The package AGENTS.md has the transcript rules.
|
|
9
9
|
*/
|
|
10
10
|
export declare function createReadMeetingTranscriptTool(ctx: GoogleToolContext): import("@sentry/junior-plugin-api").PluginToolDefinition<{
|
|
11
11
|
eventId: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/junior-google",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.269.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"commander": "^14.0.3",
|
|
26
26
|
"drizzle-orm": "^0.45.2",
|
|
27
27
|
"zod": "^4.5.4",
|
|
28
|
-
"@sentry/junior-plugin-api": "0.
|
|
28
|
+
"@sentry/junior-plugin-api": "0.269.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@oxlint/plugins": "1.79.0",
|