Repository navigation
Conversation
…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>
45f2db4 to
5b0730a
Compare
| Today is {CURRENT_DATE}. | ||
| Today is {CURRENT_DATE}.{CURRENT_TIME} |
There was a problem hiding this comment.
wdyt of passing just the date and the timezone since after some time in the chat session or picking it up again, the time would be off, so would the date but that wouldn't affect that many sessions, only the ones that span across days.
There was a problem hiding this comment.
Not a concern, substituted inside call_model on every LLM round (and every turn of a resumed session), recomputes the current date/time anew
There was a problem hiding this comment.
ah you're right, damn, but that's all the more reason to not include the time in the system prompt, it would bust the cache every second.
what do you think about adding a new tool for "date + time + user's timezone" instead?
(for later reference: https://github.com/nextcloud/context_agent/blob/ee5df89e3dcb71f05d2665647adf27d023f7fa96/ex_app/lib/agent.py #L212-L218)
There was a problem hiding this comment.
Did some digging: prefix caching needs byte identical prefixes, and dynamic timestamps in system prompts are a known cache killer in production, e.g. openclaw hit exactly this and paid 10x (openclaw#19534), the date itself is byte stable within a day though, so only the current time breaks the cache on every call.
Claude.ai itself uses "current date in the system prompt, injected once per conversation" (Claude system prompt docs, Claude 4 prompt analysis) plus an official time MCP reference server for precise time (modelcontextprotocol/servers/src/time), and the general rule is stable content before variable content with cache points after the stable part (AWS Bedrock prompt caching).
what do you think about adding a new tool for "date + time + user's timezone" instead?
So i'd follow that pattern: keep the date in the prompt, drop the time, add a small get_current_datetime tool. "tomorrow at noon" needs the date and the tz, not the minute.
…f requiring it Signed-off-by: WSHAPER <42714629+WSHAPER@users.noreply.github.com>
There was a problem hiding this comment.
add_task and update_task might also required the timezone checks.
would also be nice to include "Omit start_time and end_time parameters to create an all-day event." in the prompt as schedule_task defines.
There was a problem hiding this comment.
add_task and update_task do the check after the fallback, the omit line is already in the schedule_event description (calendar.py:133), or did you mean somewhere else?
…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>
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).