calendar.updateEvent: `attendees` replaces the guest list, so "add a guest" silently removes the others
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 58/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Tranquilla
- Stack tecnologico
- typescript
Direzione di ricerca
Inizia in CalendarService.ts, in updateEvent, e ispeziona la definizione di UpdateEventInput e lo schema dello strumento in index.ts. Esegui la suite completa, comprese le asserzioni sull’unione dei partecipanti, e verifica che l’aggiunta di invitati preservi gli oggetti dei partecipanti esistenti, che la rimozione funzioni, che un elenco vuoto elimini gli invitati e che gli aggiornamenti senza campi dei partecipanti evitino la lettura aggiuntiva.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
calendar.updateEvent treats attendees as a full replacement of the guest list. So the most common phrasing a user gives an agent — "add Ana to that meeting" — silently removes everyone else who was already invited.
This is not the events.update vs events.patch bug (that one is fixed; updateEvent correctly uses patch today). patch merges at the field level, but attendees is a single field holding an array, and Google replaces the array wholesale. So a partial body still wipes the other guests, and the API returns 200 with the stripped guest list.
Reproduction
- Create an event with attendees
[email protected]and[email protected]. calendar.updateEvent({ eventId, attendees: ["[email protected]"] }).- The event now has exactly one attendee,
[email protected].a@andb@were removed, and they receive cancellation notices.
Proposal
Make attendees mean add, which is what a caller asking to add a guest means, and add an explicit removeAttendees for the opposite intent — a merge alone can never remove anybody, so the removal case needs its own door.
One deliberate exception preserves existing behaviour: an empty attendees array still writes straight through as "clear the guest list". Merging there would make the one intent that cannot be expressed any other way impossible, and it keeps the current semantics (and its test) intact.
Patch
CalendarService.ts, in updateEvent, replacing:
if (attendees !== undefined)
requestBody.attendees = attendees.map((email) => ({ email }));
with:
// Attendees need read-modify-write even under patch: Google replaces the
// whole array rather than merging into it, so "add one guest" has to
// resend everyone.
if (attendees?.length === 0 && !removeAttendees?.length) {
requestBody.attendees = [];
} else if (attendees?.length || removeAttendees?.length) {
const current = await calendar.events.get({
calendarId: finalCalendarId,
eventId,
});
const dropped = new Set((removeAttendees ?? []).map((e) => e.toLowerCase()));
const merged = new Map<string, calendar_v3.Schema$EventAttendee>();
for (const a of current.data.attendees ?? []) {
const email = a.email?.toLowerCase();
if (!email || dropped.has(email)) continue;
merged.set(email, a);
}
for (const email of attendees ?? []) {
const key = email.toLowerCase();
if (dropped.has(key) || merged.has(key)) continue;
merged.set(key, { email });
}
requestBody.attendees = [...merged.values()];
}
Plus removeAttendees?: string[] on UpdateEventInput, and on the tool schema in index.ts:
attendees: z
.array(z.string())
.optional()
.describe(
'Email addresses to ADD as attendees. Merged with the guests already on the event, so existing guests are kept. Use removeAttendees to drop someone.',
),
removeAttendees: z
.array(z.string())
.optional()
.describe('Email addresses to remove from the event.'),
Notes on the details that matter:
- Existing attendee objects are re-sent whole, not rebuilt from the email, so each guest keeps their
responseStatus. Rebuilding them would reset everyone toneedsActionand re-notify the whole list. - Comparison is case-insensitive, since Google is.
- The read is skipped entirely when neither list is given, so the common "just change the title" path still costs one API call.
Verification
- Full suite green. The merge assertions were watched fail first by reverting the code to replacement semantics, before being trusted.
- Live against the Google API: adding a second guest to an event that already had one leaves both on the event, with the first guest's response status preserved.
Trade-off, stated plainly
This changes the meaning of attendees on update, so it is a behaviour change, not a pure bug fix. The argument for it is that the current meaning is the one nobody asks for: an agent told "add someone" has no way to comply without first reading the event itself, and every client that does not know to do that silently destroys data. If you would rather keep replacement and add addAttendees/removeAttendees as new fields, the same merge logic applies unchanged.
Happy to open a PR, though the CLA is a gate on our side — the patch above is complete either way.
- Lingua principale
- TypeScript
- Stelle
- 648
- Fork
- 107
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di gemini-cli-extensions/workspace
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
-
Project StatusAperta
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 20/100
-
feat(sheets): expose spreadsheets.batchUpdate for formatting and structural editsForse già presa @tmack8001 l’ha presa 6 giorni fa. Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 25/100
gemini-cli-extensions/workspace#450 · 2 commenti ·
Tutte le issue di gemini-cli-extensions/workspace
Issue simili
-
Shell: serve the home app's Cookie Policy on a hard reloadForse già presa @2001anshkaushik l’ha presa oggi. Apertafeature module:ai
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
rocketride-org/rocketride-server#2899 · 1 commento ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
wazuh/wazuh-dashboard-plugins#9551 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
gofish-graphics/gofish-graphics#1252 ·
I maintainer di solito rispondono entro 1 giorno
-
optimization P3 size:XS
Difficoltà 1/5 1-3 ore Idoneità per principianti 88/100
josephfung/curia#2366 ·
I maintainer di solito rispondono entro 1 giorno
-
stranded-follow-up sweep trusts any issue whose body carries the marker as the tracking issueApertatype:bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
nightgauge/nightgauge#2688 ·
I maintainer di solito rispondono entro 1 giorno