Repository navigation
fix(tools): require timezone on time tools, inject user timezone into the prompt - #257
Conversation
45f2db4 to
5b0730a
Compare
|
round 3 @kyteinsky
|
|
@kyteinsky Thanks again for the review! FYI: I've opened another can of worms that surfaced after inspecting what would be optimal for conversation branching:
In light of that, we'd need to discuss how we'd like to proceed. |
…server's Time-related tools treated the timezone parameter as optional and silently dropped it when the model omitted it, so "tomorrow at noon" resolved against server-local or UTC time. The system prompt tried to compensate by asking the model to discover the user's timezone through a find_details_of_current_user tool call first — that costs an extra agent round trip and still leaves the tools unvalidated, so any model that skipped the discovery step produced events at the wrong wall-clock time. Making the timezone a required, pytz-validated parameter on every tool that interprets a date moves the failure to the tool boundary, where a missing or invalid IANA name returns an actionable error to the model instead of silently scheduling six hours off. Injecting the requesting user's actual timezone (OCS /cloud/user) into the system prompt gives the model the correct value up front, keeping the tool-based lookup only as a fallback for profiles without a timezone set. Naive datetime.utcnow() in the free-slot search was replaced with timezone-aware UTC because mixing naive and aware comparisons produced wrong free/busy windows at DST boundaries. Verified end to end against a CEST server with the user's timezone set to America/New_York: the system prompt logs the current time in NY and "tomorrow at noon" is stored as DTSTART:20261007T160000Z (12:00 EDT). Assisted-by: opencode:zai/glm-5.3 Signed-off-by: WSHAPER <42714629+WSHAPER@users.noreply.github.com>
…g to UTC schedule_event built VEVENTs with the ics library, which serializes any aware datetime to UTC. The stored event kept the right instant but lost the timezone it was created in: edits across DST boundaries and anyone reading the raw ICS lost the anchor (issue nextcloud#231, same class as nextcloud#3 — correct data, wrong localization contract). Building the event with icalendar, already a dependency, keeps DTSTART/DTEND as DTSTART;TZID=… exactly as supplied. The organizer's email is optional in the user profile, so the mailto value must tolerate None the way the previous Organizer constructor did. Verified end to end: 'tomorrow at noon' from an America/New_York profile on a CEST server stores as DTSTART;TZID=America/New_York:…T120000. Assisted-by: opencode:zai/glm-5.3 Signed-off-by: WSHAPER <42714629+WSHAPER@users.noreply.github.com>
…f requiring it Signed-off-by: WSHAPER <42714629+WSHAPER@users.noreply.github.com>
…pper-level tz check Review round 2: the tz helpers move to all_tools/lib/tz.py (get_timezone, user_timezone, starts_at_timestamp) so calendar and assignments share one implementation, with type hints. Optional parameters carry explicit None defaults everywhere the agent can omit them. The async wrappers for schedule_event/add_task/update_task called the validation on the raw parameter, before the profile-timezone fallback in the sync bodies, so an omitted timezone errored even when the profile had one; the wrappers now only delegate. The scheduled-task starts_at docstring drops the stale find_details_of_current_user hint since the timezone defaults to the profile. Assisted-by: opencode:zai/glm-5.3 Signed-off-by: WSHAPER <42714629+WSHAPER@users.noreply.github.com>
Assisted-by: opencode:zai/glm-5.3 Signed-off-by: WSHAPER <42714629+WSHAPER@users.noreply.github.com>
Signed-off-by: WSHAPER <42714629+WSHAPER@users.noreply.github.com>
Assisted-by: opencode:zai/glm-5.3 Signed-off-by: WSHAPER <42714629+WSHAPER@users.noreply.github.com>
Signed-off-by: WSHAPER <42714629+WSHAPER@users.noreply.github.com>
Assisted-by: opencode:zai/glm-5.3 Signed-off-by: WSHAPER <42714629+WSHAPER@users.noreply.github.com>
Signed-off-by: WSHAPER <42714629+WSHAPER@users.noreply.github.com>
15a86c0 to
ec291c0
Compare
|
rebased onto impulse-radius; tz semantics unchanged, tools ride the impulse classification now, payload tests still green. |
Follow-up to nextcloud#257: - update_scheduled_task sent the profile timezone on every update, silently moving tasks stored in another timezone, and failed for users without a profile timezone. It now only sends a timezone when one is given explicitly. - create_scheduled_task failed for users without a profile timezone even when no starts_at was given. A timezone is now only required to interpret a starts_at without UTC offset. - update_task resolved the timezone inside a bare except, so an invalid or missing timezone was swallowed and reported as "task not found". It is now resolved before the loop. - The starts_at docs no longer show a UTC example, which made the model send local times with a Z suffix. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Marcel Klehr <mklehr@gmx.net>
|
Hello there, We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process. Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6 Thank you for contributing to Nextcloud and we hope to hear from you soon! (If you believe you should not receive this message, you can add yourself to the blocklist.) |
Fixes #3
Fixes #231
timezoneis now a required,pytz-validated parameter onschedule_event/add_task/update_taskand the scheduled-task tools; a missing or invalid IANA name returns an actionable error to the model instead of silently resolving the time in server/UTC. The system prompt now carries the requesting user's actual timezone (OCS/cloud/user) plus the current time in that tz.The
find_details_of_current_userinstruction stays as a fallback for profiles without a timezone.freebusy_finder's naiveutcnow()became tz-aware UTC.For #231, schedule_event now builds the event with
icalendarinstead of theicslibrary (which serializes any aware datetime to UTC): DTSTART/DTEND keep the supplied timezone asDTSTART;TZID=…. The organizer's mailto tolerates profiles without an email, as before.Heads-up: tool callers (incl. MCP) that omitted
timezonepreviously got a silently mis-timezoned event; they now get an explicit error, which should be the canonical behavior, in my opinion.Verified on stable35 / context_agent 2.9.1, user tz America/New_York on a CEST server: "tomorrow at noon" stores as 12:00 America/New_York (DTSTART:...T160000Z).