Skip to content

Use client browser timezone instead of server timezone for agent tools#40

Merged
NanaKay007 merged 2 commits into
mainfrom
fix/client-timezone-handling
Jan 31, 2026
Merged

Use client browser timezone instead of server timezone for agent tools#40
NanaKay007 merged 2 commits into
mainfrom
fix/client-timezone-handling

Conversation

@NanaKay007

Copy link
Copy Markdown
Owner

Summary

  • Agent tools (get_current_datetime, datetime_math, list_events, search_events) were using the server's timezone via DateTime.now().zoneName, producing wrong results when server and user are in different timezones
  • create_event and update_event tools had no timezone context, so calendarService fell back to UTC for the Google Calendar API timeZone field
  • Frontend now sends Intl.DateTimeFormat().resolvedOptions().timeZone (IANA timezone, e.g. "America/New_York") with every WebSocket message
  • Backend threads the client timezone through ws.tschatServicecreateCalendarAgent → all timezone-aware tools

Files changed

  • app/src/services/chatService.ts — adds timezone to WS payload
  • backend/src/ws.ts — extracts timezone from message, passes to chatService
  • backend/src/services/chat.service.ts — forwards timezone to agent
  • backend/src/agent/agent.ts — passes timezone to all tools
  • backend/src/agent/tools/getCurrentDateTimeTool.ts — uses client timezone for DateTime.now()
  • backend/src/agent/tools/dateTimeMathTool.ts — uses client timezone for ambiguous datetimes
  • backend/src/agent/tools/listEventsTool.ts — converts event times to client timezone
  • backend/src/agent/tools/searchEventsTool.ts — converts event times to client timezone
  • backend/src/agent/tools/createEventTool.ts — injects client timezone into pending action payload
  • backend/src/agent/tools/updateEventTool.ts — injects client timezone into pending action payload

Test plan

  • Verify get_current_datetime returns the user's local time, not the server's
  • Verify events listed by the agent show times in the user's timezone
  • Verify created events have the correct timezone in Google Calendar
  • Verify fallback behavior when timezone is not provided (gracefully uses server timezone)

🤖 Generated with Claude Code

NanaKay007 and others added 2 commits January 31, 2026 11:44
The agent's datetime tools (get_current_datetime, datetime_math, list_events,
search_events) were using the server's timezone via DateTime.now().zoneName,
which is wrong when the server runs in a different timezone than the user.
Similarly, create/update event tools had no timezone context, causing
calendarService to fall back to UTC.

Fix: the frontend sends its IANA timezone (from Intl.DateTimeFormat) with
every WebSocket message. The backend threads it through chatService →
createCalendarAgent → all tools that need timezone awareness.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@claude

claude Bot commented Jan 31, 2026

Copy link
Copy Markdown

PR Review - Timezone Support Implementation

Critical Issues

1. Security: Missing Timezone Validation (HIGH SEVERITY)

Location: backend/src/ws.ts:85

The client-provided timezone is accepted without validation:

const timezone = typeof parsed.timezone === 'string' ? parsed.timezone : undefined;

Risk: A malicious client could send arbitrary strings that may cause crashes or unexpected behavior in Luxon's DateTime.setZone() or DateTime.fromISO() methods.

Fix Required: Validate the timezone string against IANA timezone database before use:

import { DateTime } from 'luxon';

function isValidTimezone(tz: string): boolean {
  try {
    return DateTime.local().setZone(tz).isValid;
  } catch {
    return false;
  }
}

const timezone = typeof parsed.timezone === 'string' && isValidTimezone(parsed.timezone) 
  ? parsed.timezone 
  : undefined;

2. Bug: Ambiguous Datetime Handling

Location: backend/src/agent/tools/dateTimeMathTool.ts:13-16

The regex pattern used to detect timezone-aware datetimes is fragile:

if (clientTimezone && !input.datetime!.match(/[+-]\d{2}:\d{2}$|Z$/)) {
  dt = DateTime.fromISO(input.datetime!, { zone: clientTimezone });
}

Issues:

  • Doesn't handle all ISO 8601 formats (e.g., +0530, +05)
  • May incorrectly apply client timezone to dates that already have timezone info in other formats

Recommendation: Use Luxon's timezone detection capabilities more robustly or explicitly require timezone info in the input.

Code Quality Issues

3. Missing Integration Tests (Per CLAUDE.md requirement)

According to CLAUDE.md:4, all code must have integration tests. This PR lacks timezone-specific integration tests covering:

  • Timezone validation edge cases
  • Event creation/update with various timezone formats
  • Timezone conversion accuracy across DST boundaries
  • Fallback behavior when timezone is invalid/missing

4. Incomplete Error Handling

Location: Multiple tool files

If DateTime.setZone() receives an invalid timezone, it may return an invalid DateTime object rather than throwing an error. The code doesn't check dt.isValid before using the datetime.

Example in getCurrentDateTimeTool.ts:7-9:

const now = clientTimezone
  ? DateTime.now().setZone(clientTimezone)
  : DateTime.now();

Should be:

const now = clientTimezone
  ? DateTime.now().setZone(clientTimezone)
  : DateTime.now();

if (!now.isValid) {
  return JSON.stringify({ error: 'Invalid timezone provided' });
}

Minor Issues

5. Inconsistent Fallback Behavior

The PR description mentions "graceful fallback" when timezone is not provided, but the actual fallback varies:

  • getCurrentDateTimeTool.ts: Falls back to server timezone
  • createEventTool.ts: Falls back to client timezone then potentially undefined → UTC (via calendarService.ts:136)
  • dateTimeMathTool.ts: No fallback mentioned

This inconsistency could lead to confusion.

Summary

Must Fix Before Merge:

  1. Add timezone validation in ws.ts to prevent injection of invalid timezone strings
  2. Add integration tests as required by CLAUDE.md
  3. Add isValid checks after all setZone() operations

Recommended:
4. Improve datetime parsing logic in dateTimeMathTool.ts
5. Document and standardize fallback behavior across all tools

The core approach is sound, but security validation and test coverage are critical gaps that must be addressed.

@NanaKay007 NanaKay007 merged commit c46961a into main Jan 31, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant