fix(google-calendar): address review findings

- log an unknown stored zone once even when the tool description reads it first
- serialise the flow's token write with /calendar_disconnect under the flow gate
- a cancelled or expired pending flow is cleared, not re-sent or shown
- chat keys anchor with \z so a trailing newline is hashed
- a timeMax date includes that whole day (spec updated)
- dispose the flow's CancellationTokenSource, drop ConnectFlow.Token, Begin is a plain write
- GoogleCalendarOptions.IsConfigured replaces the host's copy of the rule; StoredToken is internal
- test BotSetupService's menu through DI, tokens absent from tool results
- Telegram.Tests csproj reference placed as in telegram-message-context; ChatHost passes calendar by name
- docs: per-event timeZone, both config sources for /calendar_*
This commit is contained in:
EugeneTes
2026-09-26 20:30:56 +02:00
parent 8ece6f303d
commit 881e7f0be9
22 changed files with 242 additions and 36 deletions

View File

@@ -123,14 +123,18 @@ The refresh token never appears in logs, tool results or error messages.
## Time zones
- Times without an offset (`2026-09-30T10:00`) are in the calendar's own time zone, which the bot reads when the chat
connects. If that's unknown, they are in the chat's zone.
- `create` and `update` take an optional `timeZone` (an IANA id such as `Europe/Berlin`) for the event. Times without
an offset are then in that zone.
- Otherwise times without an offset (`2026-09-30T10:00`) are in the calendar's own time zone, which the bot reads when
the chat connects. If that's unknown, they are in the chat's zone.
- A time with an offset (`2026-09-30T10:00:00+02:00`) keeps its offset.
- Every tool result starts with the zone it uses, such as `Times in Europe/Berlin.` When the calendar's zone differs
from the chat's, the header names both:
`Times in America/New_York (the calendar's zone; this chat is in Europe/Berlin).`
- A date alone (`2026-09-30`) is an all-day event. All-day ends are exclusive, as in Google: an event on the 30th ends
on the 1st.
- In a `list` or `search` window, a `timeMax` date includes that day: `timeMin` and `timeMax` both `2026-09-30` cover
the whole 30th.
- For recurring events, `list_instances` returns the ids of single occurrences. `update` and `delete` detect whether an
id is one occurrence or a whole series, so `scope` (`instance` or `series`) only needs to be passed to be explicit.
"This and following" edits aren't supported.