@sentry/junior-google 0.239.0 → 0.241.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 CHANGED
@@ -15,9 +15,12 @@ This version supports Calendar only. Drive and Gmail are out of scope.
15
15
  Slots where they are free come first, and each slot names the optional
16
16
  attendees who are busy or off hours. Slots are spread across days and
17
17
  across each day, so the requester gets a real choice.
18
+ - Every Calendar tool takes an optional `timeZone` for the times it reads and
19
+ shows. Without it, the tool uses the requester's timezone from
20
+ `ctx.users.resolveTimezone()`, so Junior does not have to ask for one.
18
21
  - `createCalendarEvent` creates an event on Junior's own calendar. It sends
19
- invites and can add a Google Meet link, a location, optional attendees, and
20
- a simple repeat rule (weekdays, weekly, or monthly). A retry of the same
22
+ invites and always adds a Google Meet link. It can add a location, optional
23
+ attendees, and a simple repeat rule (weekdays, weekly, or monthly). A retry of the same
21
24
  tool call returns the same event. It does not create a second invite.
22
25
  - `listCalendarEvents` reads the events on one colleague's calendar, or on
23
26
  Junior's own calendar when no calendar is given. It shows only what the
package/dist/index.js CHANGED
@@ -744,8 +744,8 @@ import {
744
744
  } from "@sentry/junior-plugin-api";
745
745
  import { z as z2 } from "zod";
746
746
  var emailListSchema = (max) => z2.array(z2.string().trim().toLowerCase().pipe(z2.email())).max(max).describe("Attendee email addresses.");
747
- var timeZoneSchema = z2.string().min(1).refine(isTimeZone, "timeZone must be an IANA time zone").describe(
748
- "IANA time zone used to read and show times, such as America/Los_Angeles."
747
+ var timeZoneSchema = z2.string().min(1).refine(isTimeZone, "timeZone must be an IANA time zone").optional().describe(
748
+ "IANA time zone used to read and show times, such as America/Los_Angeles. Omit to use the requester's time zone."
749
749
  );
750
750
  function isTimeZone(value) {
751
751
  try {
@@ -1003,6 +1003,7 @@ function createCancelCalendarEventTool(ctx) {
1003
1003
  inputSchema,
1004
1004
  outputSchema,
1005
1005
  async execute(input) {
1006
+ const timeZone = input.timeZone ?? await ctx.users.resolveTimezone();
1006
1007
  const read = await readOwnEventForRequester(ctx, input.eventId, "cancel");
1007
1008
  if (read.status === "cancelled") {
1008
1009
  return {
@@ -1014,7 +1015,7 @@ function createCancelCalendarEventTool(ctx) {
1014
1015
  const { event, path } = read;
1015
1016
  const result = {
1016
1017
  target: "cancelCalendarEvent",
1017
- ...ownEventResult(event, input.timeZone)
1018
+ ...ownEventResult(event, timeZone)
1018
1019
  };
1019
1020
  const response = await googleApiRequest(ctx, {
1020
1021
  operation: "google.calendar.event.delete",
@@ -1077,7 +1078,6 @@ var inputSchema2 = z4.object({
1077
1078
  "Email addresses of required attendees. Junior adds the requester automatically when it knows their email."
1078
1079
  ),
1079
1080
  optionalAttendees: emailListSchema(50).default([]).describe("Email addresses to invite as optional attendees."),
1080
- addVideoCall: z4.boolean().default(true).describe("Add a Google Meet link."),
1081
1081
  repeat: repeatSchema.optional().describe("Make a repeating series, such as a weekly 1:1.")
1082
1082
  }).strict();
1083
1083
  var outputSchema2 = pluginToolOutputSchema2.extend({
@@ -1101,10 +1101,11 @@ function createCreateCalendarEventTool(ctx) {
1101
1101
  const repeat = input.repeat ? `, repeating ${recurrenceRule(input.repeat)}` : "";
1102
1102
  return `Create Google Calendar event "${input.title}" from ${input.start} to ${input.end}${repeat} and email invites to ${input.attendees.join(", ") || "the requester"}${optional}.`;
1103
1103
  },
1104
- description: "Create a Google Calendar event organized by Junior's own Google account and email invites to the attendees. Junior can later change or cancel it. Use after the requester confirms the time, or when they already gave an exact time. Check the time with findMeetingTimes first unless the requester says to book it anyway. Only people in the company's Google Workspace domains can be invited.",
1104
+ description: "Create a Google Calendar event organized by Junior's own Google account and email invites to the attendees. Every event gets a Google Meet link. Junior can later change or cancel it. Use after the requester confirms the time, or when they already gave an exact time. Check the time with findMeetingTimes first unless the requester says to book it anyway. Only people in the company's Google Workspace domains can be invited.",
1105
1105
  inputSchema: inputSchema2,
1106
1106
  outputSchema: outputSchema2,
1107
1107
  async execute(input, options) {
1108
+ const timeZone = input.timeZone ?? await ctx.users.resolveTimezone();
1108
1109
  const startMs = Date.parse(input.start);
1109
1110
  const endMs = Date.parse(input.end);
1110
1111
  if (endMs <= startMs) {
@@ -1132,27 +1133,25 @@ function createCreateCalendarEventTool(ctx) {
1132
1133
  ...attendees.map((email) => ({ email })),
1133
1134
  ...optionalAttendees.map((email) => ({ email, optional: true }))
1134
1135
  ],
1135
- ...input.addVideoCall ? {
1136
- conferenceData: {
1137
- createRequest: {
1138
- conferenceSolutionKey: { type: "hangoutsMeet" },
1139
- requestId: eventId
1140
- }
1136
+ conferenceData: {
1137
+ createRequest: {
1138
+ conferenceSolutionKey: { type: "hangoutsMeet" },
1139
+ requestId: eventId
1141
1140
  }
1142
- } : void 0,
1141
+ },
1143
1142
  ...input.description ? { description: input.description } : void 0,
1144
- end: { dateTime: input.end, timeZone: input.timeZone },
1143
+ end: { dateTime: input.end, timeZone },
1145
1144
  guestsCanModify: false,
1146
1145
  id: eventId,
1147
1146
  ...input.location ? { location: input.location } : void 0,
1148
1147
  ...input.repeat ? { recurrence: [recurrenceRule(input.repeat)] } : void 0,
1149
- start: { dateTime: input.start, timeZone: input.timeZone },
1148
+ start: { dateTime: input.start, timeZone },
1150
1149
  summary: input.title
1151
1150
  },
1152
1151
  operation: "google.calendar.event.create",
1153
1152
  path: "/calendar/v3/calendars/primary/events",
1154
1153
  query: {
1155
- conferenceDataVersion: input.addVideoCall ? "1" : "0",
1154
+ conferenceDataVersion: "1",
1156
1155
  sendUpdates: "all"
1157
1156
  }
1158
1157
  });
@@ -1173,7 +1172,7 @@ function createCreateCalendarEventTool(ctx) {
1173
1172
  return {
1174
1173
  target: "createCalendarEvent",
1175
1174
  created,
1176
- ...ownEventResult(ownEventSchema.parse(event.body), input.timeZone)
1175
+ ...ownEventResult(ownEventSchema.parse(event.body), timeZone)
1177
1176
  };
1178
1177
  }
1179
1178
  });
@@ -1205,7 +1204,7 @@ var inputSchema3 = z5.object({
1205
1204
  "End of the search window, RFC 3339 with offset. Defaults to 7 days after timeMin. At most 14 days after timeMin."
1206
1205
  ),
1207
1206
  timeZone: timeZoneSchema.describe(
1208
- "The requester's IANA time zone, such as America/Los_Angeles. Slot labels use it. It is also the working-hours zone for anyone whose calendar time zone Junior cannot read."
1207
+ "IANA time zone for slot labels, such as America/Los_Angeles. Omit to use the requester's time zone. It is also the working-hours zone for anyone whose calendar time zone Junior cannot read."
1209
1208
  ),
1210
1209
  workdayStart: clockTimeSchema.default("09:00").describe(
1211
1210
  "Earliest local start, 24-hour HH:MM, in each attendee's own calendar time zone."
@@ -1397,6 +1396,7 @@ function createFindMeetingTimesTool(ctx) {
1397
1396
  inputSchema: inputSchema3,
1398
1397
  outputSchema: outputSchema3,
1399
1398
  async execute(input) {
1399
+ const timeZone = input.timeZone ?? await ctx.users.resolveTimezone();
1400
1400
  const timeMinMs = Math.max(
1401
1401
  input.timeMin ? Date.parse(input.timeMin) : 0,
1402
1402
  Date.now()
@@ -1448,8 +1448,11 @@ function createFindMeetingTimesTool(ctx) {
1448
1448
  unavailable2.push({ email, reason: error ?? "notFound" });
1449
1449
  return;
1450
1450
  }
1451
- const timeZone = timeZones[index];
1452
- checked.push({ email, ...timeZone ? { timeZone } : void 0 });
1451
+ const calendarZone = timeZones[index];
1452
+ checked.push({
1453
+ email,
1454
+ ...calendarZone ? { timeZone: calendarZone } : void 0
1455
+ });
1453
1456
  slotAttendees.push({
1454
1457
  busy: calendar.busy.map((interval) => ({
1455
1458
  endMs: Date.parse(interval.end),
@@ -1457,7 +1460,7 @@ function createFindMeetingTimesTool(ctx) {
1457
1460
  })),
1458
1461
  email,
1459
1462
  required: required.has(email),
1460
- timeZone: timeZone ?? input.timeZone
1463
+ timeZone: calendarZone ?? timeZone
1461
1464
  });
1462
1465
  });
1463
1466
  const slots = !slotAttendees.some((attendee) => attendee.required) ? [] : findFreeSlots({
@@ -1466,28 +1469,28 @@ function createFindMeetingTimesTool(ctx) {
1466
1469
  maxResults: input.maxResults,
1467
1470
  timeMaxMs,
1468
1471
  timeMinMs,
1469
- timeZone: input.timeZone,
1472
+ timeZone,
1470
1473
  workdayEnd: input.workdayEnd,
1471
1474
  workdayStart: input.workdayStart
1472
1475
  });
1473
1476
  const otherTimeZones = [
1474
1477
  ...new Set(slotAttendees.map((attendee) => attendee.timeZone))
1475
- ].filter((timeZone) => timeZone !== input.timeZone);
1478
+ ].filter((zone) => zone !== timeZone);
1476
1479
  return {
1477
1480
  target: "findMeetingTimes",
1478
1481
  checked,
1479
1482
  slots: slots.map((slot) => ({
1480
1483
  end: new Date(slot.endMs).toISOString(),
1481
- label: formatInterval(slot.startMs, slot.endMs, input.timeZone),
1484
+ label: formatInterval(slot.startMs, slot.endMs, timeZone),
1482
1485
  ...otherTimeZones.length ? {
1483
1486
  otherTimeZoneLabels: otherTimeZones.map(
1484
- (timeZone) => formatInterval(slot.startMs, slot.endMs, timeZone)
1487
+ (zone) => formatInterval(slot.startMs, slot.endMs, zone)
1485
1488
  )
1486
1489
  } : void 0,
1487
1490
  ...slot.optionalConflicts.length ? { optionalConflicts: slot.optionalConflicts } : void 0,
1488
1491
  start: new Date(slot.startMs).toISOString()
1489
1492
  })),
1490
- timeZone: input.timeZone,
1493
+ timeZone,
1491
1494
  unavailable: unavailable2
1492
1495
  };
1493
1496
  }
@@ -1591,6 +1594,7 @@ function createListCalendarEventsTool(ctx) {
1591
1594
  inputSchema: inputSchema4,
1592
1595
  outputSchema: outputSchema4,
1593
1596
  async execute(input) {
1597
+ const timeZone = input.timeZone ?? await ctx.users.resolveTimezone();
1594
1598
  const timeMinMs = Date.parse(input.timeMin);
1595
1599
  const timeMaxMs = Date.parse(input.timeMax);
1596
1600
  if (timeMaxMs <= timeMinMs) {
@@ -1610,13 +1614,13 @@ function createListCalendarEventsTool(ctx) {
1610
1614
  singleEvents: "true",
1611
1615
  timeMax: new Date(timeMaxMs).toISOString(),
1612
1616
  timeMin: new Date(timeMinMs).toISOString(),
1613
- timeZone: input.timeZone
1617
+ timeZone
1614
1618
  }
1615
1619
  });
1616
1620
  const result = {
1617
1621
  target: "listCalendarEvents",
1618
1622
  calendar,
1619
- timeZone: input.timeZone
1623
+ timeZone
1620
1624
  };
1621
1625
  if (response.status === 404) {
1622
1626
  return { ...result, events: [], truncated: false, visible: false };
@@ -1630,7 +1634,7 @@ function createListCalendarEventsTool(ctx) {
1630
1634
  events: items.filter((event) => event.status !== "cancelled").map((event) => ({
1631
1635
  end: event.end.dateTime ?? lastAllDayDate(event.end) ?? "",
1632
1636
  eventId: event.id,
1633
- label: eventLabel(event.start, event.end, input.timeZone),
1637
+ label: eventLabel(event.start, event.end, timeZone),
1634
1638
  start: event.start.dateTime ?? event.start.date ?? "",
1635
1639
  ...event.summary ? { title: event.summary } : void 0,
1636
1640
  ...event.location ? { location: event.location } : void 0,
@@ -1709,6 +1713,7 @@ function createUpdateCalendarEventTool(ctx) {
1709
1713
  inputSchema: inputSchema5,
1710
1714
  outputSchema: outputSchema5,
1711
1715
  async execute(input) {
1716
+ const timeZone = input.timeZone ?? await ctx.users.resolveTimezone();
1712
1717
  if (input.start && input.end) {
1713
1718
  const durationMs = Date.parse(input.end) - Date.parse(input.start);
1714
1719
  if (durationMs <= 0) {
@@ -1758,8 +1763,8 @@ function createUpdateCalendarEventTool(ctx) {
1758
1763
  description: input.description
1759
1764
  },
1760
1765
  ...input.start && input.end && {
1761
- end: { dateTime: input.end, timeZone: input.timeZone },
1762
- start: { dateTime: input.start, timeZone: input.timeZone }
1766
+ end: { dateTime: input.end, timeZone },
1767
+ start: { dateTime: input.start, timeZone }
1763
1768
  },
1764
1769
  ...input.location !== void 0 && { location: input.location },
1765
1770
  ...attendeesChanged && { attendees: [...kept, ...added] },
@@ -1784,7 +1789,7 @@ function createUpdateCalendarEventTool(ctx) {
1784
1789
  }
1785
1790
  return {
1786
1791
  target: "updateCalendarEvent",
1787
- ...ownEventResult(ownEventSchema.parse(response.body), input.timeZone)
1792
+ ...ownEventResult(ownEventSchema.parse(response.body), timeZone)
1788
1793
  };
1789
1794
  }
1790
1795
  });
@@ -8,7 +8,7 @@ import { type GoogleToolContext } from "./shared";
8
8
  */
9
9
  export declare function createCancelCalendarEventTool(ctx: GoogleToolContext): import("@sentry/junior-plugin-api").PluginToolDefinition<{
10
10
  eventId: string;
11
- timeZone: string;
11
+ timeZone?: string | undefined;
12
12
  }, {
13
13
  [x: string]: unknown;
14
14
  eventId: string;
@@ -24,12 +24,11 @@ export declare function createCreateCalendarEventTool(ctx: GoogleToolContext): i
24
24
  title: string;
25
25
  start: string;
26
26
  end: string;
27
- timeZone: string;
28
27
  attendees: string[];
29
28
  optionalAttendees: string[];
30
- addVideoCall: boolean;
31
29
  description?: string | undefined;
32
30
  location?: string | undefined;
31
+ timeZone?: string | undefined;
33
32
  repeat?: {
34
33
  frequency: "weekdays" | "weekly" | "monthly";
35
34
  interval: number;
@@ -43,12 +43,12 @@ export declare function createFindMeetingTimesTool(ctx: GoogleToolContext): impo
43
43
  attendees: string[];
44
44
  optionalAttendees: string[];
45
45
  durationMinutes: number;
46
- timeZone: string;
47
46
  workdayStart: string;
48
47
  workdayEnd: string;
49
48
  maxResults: number;
50
49
  timeMin?: string | undefined;
51
50
  timeMax?: string | undefined;
51
+ timeZone?: string | undefined;
52
52
  }, {
53
53
  [x: string]: unknown;
54
54
  target: "findMeetingTimes";
@@ -9,9 +9,9 @@ import { type GoogleToolContext } from "./shared";
9
9
  export declare function createListCalendarEventsTool(ctx: GoogleToolContext): import("@sentry/junior-plugin-api").PluginToolDefinition<{
10
10
  timeMin: string;
11
11
  timeMax: string;
12
- timeZone: string;
13
12
  maxResults: number;
14
13
  calendar?: string | undefined;
14
+ timeZone?: string | undefined;
15
15
  }, {
16
16
  [x: string]: unknown;
17
17
  target: "listCalendarEvents";
@@ -11,10 +11,11 @@ export interface GoogleToolContext {
11
11
  resolveActor(): Promise<{
12
12
  user?: User;
13
13
  } | undefined>;
14
+ resolveTimezone(): Promise<string>;
14
15
  };
15
16
  }
16
17
  export declare const emailListSchema: (max: number) => z.ZodArray<z.ZodPipe<z.ZodString, z.ZodEmail>>;
17
- export declare const timeZoneSchema: z.ZodString;
18
+ export declare const timeZoneSchema: z.ZodOptional<z.ZodString>;
18
19
  /** True when the runtime knows this IANA time zone. */
19
20
  export declare function isTimeZone(value: string): boolean;
20
21
  /** Reject people outside the domains Junior may look up or invite. */
@@ -6,7 +6,6 @@ import { type GoogleToolContext } from "./shared";
6
6
  */
7
7
  export declare function createUpdateCalendarEventTool(ctx: GoogleToolContext): import("@sentry/junior-plugin-api").PluginToolDefinition<{
8
8
  eventId: string;
9
- timeZone: string;
10
9
  addAttendees: string[];
11
10
  addOptionalAttendees: string[];
12
11
  removeAttendees: string[];
@@ -14,6 +13,7 @@ export declare function createUpdateCalendarEventTool(ctx: GoogleToolContext): i
14
13
  description?: string | undefined;
15
14
  start?: string | undefined;
16
15
  end?: string | undefined;
16
+ timeZone?: string | undefined;
17
17
  location?: string | undefined;
18
18
  addVideoCall?: true | undefined;
19
19
  }, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/junior-google",
3
- "version": "0.239.0",
3
+ "version": "0.241.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.239.0"
28
+ "@sentry/junior-plugin-api": "0.241.0"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@oxlint/plugins": "1.79.0",