date format fix

This commit is contained in:
Roberto
2026-04-26 21:06:38 +02:00
parent 2c7cac9e03
commit cb8f56d909
5 changed files with 85 additions and 9 deletions

View File

@@ -141,11 +141,21 @@ async def delete_task(task_id: str) -> str:
@tool
async def list_tasks_due_today() -> str:
"""List all tasks whose due date falls on today's date."""
now = datetime.now(tz=timezone.utc)
start_ms = int(datetime(now.year, now.month, now.day, tzinfo=timezone.utc).timestamp() * 1000)
end_ms = start_ms + 86_400_000 - 1 # last ms of today
async def list_tasks_due_today(user_timezone: str = "UTC") -> str:
"""List all tasks whose due date falls on today's date.
user_timezone: IANA timezone name (e.g. 'Europe/Rome', 'America/New_York').
Always pass the user's timezone so 'today' is computed in their local time.
"""
try:
from zoneinfo import ZoneInfo
tz = ZoneInfo(user_timezone or "UTC")
except Exception:
tz = timezone.utc
now_local = datetime.now(tz=tz)
start_dt = datetime(now_local.year, now_local.month, now_local.day, tzinfo=tz)
start_ms = int(start_dt.timestamp() * 1000)
end_ms = start_ms + 86_400_000 - 1
result = await execute_on_client(
action="select",
table="tasks",

View File

@@ -94,10 +94,20 @@ async def delete_timeline(timeline_id: str) -> str:
@tool
async def list_timelines_today() -> str:
"""List all timeline events (milestones) whose date falls on today (UTC)."""
now = datetime.now(tz=timezone.utc)
start_ms = int(datetime(now.year, now.month, now.day, tzinfo=timezone.utc).timestamp() * 1000)
async def list_timelines_today(user_timezone: str = "UTC") -> str:
"""List all timeline events (milestones) whose date falls on today.
user_timezone: IANA timezone name (e.g. 'Europe/Rome', 'America/New_York').
Always pass the user's timezone so 'today' is computed in their local time.
"""
try:
from zoneinfo import ZoneInfo
tz = ZoneInfo(user_timezone or "UTC")
except Exception:
tz = timezone.utc
now_local = datetime.now(tz=tz)
start_dt = datetime(now_local.year, now_local.month, now_local.day, tzinfo=tz)
start_ms = int(start_dt.timestamp() * 1000)
end_ms = start_ms + 86_400_000 - 1
result = await execute_on_client(
action="select",

View File

@@ -226,6 +226,7 @@ async def _handle_home_request(
context: dict = {
"conversation_history": frame.get("conversation_history", []),
"_debug": {"request_id": request_id, "session_id": session_id, "user_id": user_id},
"format_prefs": frame.get("format_prefs"),
**memory_context,
}
@@ -295,6 +296,7 @@ async def _handle_floating_request(
context: dict = {
"scope": scope,
"_debug": {"request_id": request_id, "session_id": session_id, "user_id": user_id},
"format_prefs": frame.get("format_prefs"),
**memory_context,
}
@@ -380,6 +382,7 @@ async def _handle_brief_request(
context: dict = {
"_debug": {"request_id": request_id, "session_id": session_id, "user_id": user_id},
"format_prefs": frame.get("format_prefs"),
**memory_context,
}

View File

@@ -55,6 +55,42 @@ def _language_instruction(context: dict[str, Any]) -> str:
f"All your output text must be written in {lang}."
)
def _datetime_context_injection(context: dict[str, Any]) -> str:
"""Build a system-prompt paragraph with current timestamp, user timezone, and format prefs."""
fp = context.get("format_prefs")
if not fp or not isinstance(fp, dict):
return ""
try:
from zoneinfo import ZoneInfo
from datetime import datetime as _dt, timezone as _utc
tz_name: str = str(fp.get("timezone") or "UTC")
now_iso: str = str(fp.get("now_iso") or "")
date_fmt: str = str(fp.get("date_format") or "dd/MM/yyyy")
time_fmt: str = str(fp.get("time_format") or "24h")
if now_iso:
now_utc = _dt.fromisoformat(now_iso.replace("Z", "+00:00"))
else:
now_utc = _dt.now(_utc.utc)
tz = ZoneInfo(tz_name)
now_local = now_utc.astimezone(tz)
today_local = now_local.strftime("%Y-%m-%d")
weekday_local = now_local.strftime("%A")
return (
f"\n\nCurrent instant: {now_utc.isoformat()}. "
f"User local date: {today_local} ({weekday_local}). "
f"Timezone: {tz_name}. "
f"Display preference: dateFormat={date_fmt}, timeFormat={time_fmt}. "
f"When calling tools with date fields, always pass integer Unix milliseconds (ms since epoch, UTC). "
f"When calling list_tasks_due_today or list_timelines_today, always pass user_timezone=\"{tz_name}\". "
f"When presenting dates to the user in chat, format using the display preference above."
)
except Exception:
return ""
def _proactive_hints_injection(context: dict[str, Any]) -> str:
"""Return a system-prompt paragraph listing proactive behavioral hints.
@@ -938,6 +974,7 @@ async def run_home(user_id: str, message: str, context: dict[str, Any]) -> str:
)
system_prompt += _relational_memory_injection(context)
system_prompt += _proactive_hints_injection(context)
system_prompt += _datetime_context_injection(context)
system_prompt += _language_instruction(context)
response = await _run_single_agent(
user_id=user_id,
@@ -958,6 +995,7 @@ async def run_floating(user_id: str, message: str, context: dict[str, Any]) -> t
)
system_prompt += _relational_memory_injection(context)
system_prompt += _proactive_hints_injection(context)
system_prompt += _datetime_context_injection(context)
system_prompt += _language_instruction(context)
response = await _run_single_agent(
user_id=user_id,
@@ -984,6 +1022,7 @@ async def run_home_stream(
)
system_prompt += _relational_memory_injection(context)
system_prompt += _proactive_hints_injection(context)
system_prompt += _datetime_context_injection(context)
system_prompt += _language_instruction(context)
text_chunks: list[str] = []
async for event in _run_single_agent_stream(
@@ -1019,6 +1058,7 @@ async def run_floating_stream(
)
system_prompt += _relational_memory_injection(context)
system_prompt += _proactive_hints_injection(context)
system_prompt += _datetime_context_injection(context)
system_prompt += _language_instruction(context)
sanitizer = _FloatingStreamSanitizer()
emitted_sanitized = False

View File

@@ -142,6 +142,16 @@ class WsDeviceHello(BaseModel):
# ── WebSocket v3 Frame Models ─────────────────────────────────────────
class FormatPrefsModel(BaseModel):
"""User display preferences sent by Electron on each request."""
timezone: str = "UTC"
date_format: str = "dd/MM/yyyy"
time_format: str = "24h"
locale: str = "en-US"
now_iso: str = ""
class WsFloatingScope(BaseModel):
"""Scope for a floating request — narrows the agent to a specific entity."""
@@ -155,6 +165,7 @@ class WsHomeRequest(BaseModel):
type: Literal[WsFrameType.home_request] = WsFrameType.home_request
message: str
conversation_history: list[dict[str, Any]] = Field(default_factory=list)
format_prefs: FormatPrefsModel | None = None
class WsFloatingRequest(BaseModel):
@@ -163,6 +174,7 @@ class WsFloatingRequest(BaseModel):
type: Literal[WsFrameType.floating_request] = WsFrameType.floating_request
message: str
scope: WsFloatingScope
format_prefs: FormatPrefsModel | None = None
class WsBriefRequest(BaseModel):
@@ -173,6 +185,7 @@ class WsBriefRequest(BaseModel):
session_id: str | None = None
mode: Literal["home", "project"]
project_id: str | None = None
format_prefs: FormatPrefsModel | None = None
class WsStreamStart(BaseModel):