date format fix
This commit is contained in:
@@ -141,11 +141,21 @@ async def delete_task(task_id: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
@tool
|
@tool
|
||||||
async def list_tasks_due_today() -> str:
|
async def list_tasks_due_today(user_timezone: str = "UTC") -> str:
|
||||||
"""List all tasks whose due date falls on today's date."""
|
"""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)
|
user_timezone: IANA timezone name (e.g. 'Europe/Rome', 'America/New_York').
|
||||||
end_ms = start_ms + 86_400_000 - 1 # last ms of today
|
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(
|
result = await execute_on_client(
|
||||||
action="select",
|
action="select",
|
||||||
table="tasks",
|
table="tasks",
|
||||||
|
|||||||
@@ -94,10 +94,20 @@ async def delete_timeline(timeline_id: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
@tool
|
@tool
|
||||||
async def list_timelines_today() -> str:
|
async def list_timelines_today(user_timezone: str = "UTC") -> str:
|
||||||
"""List all timeline events (milestones) whose date falls on today (UTC)."""
|
"""List all timeline events (milestones) whose date falls on today.
|
||||||
now = datetime.now(tz=timezone.utc)
|
|
||||||
start_ms = int(datetime(now.year, now.month, now.day, tzinfo=timezone.utc).timestamp() * 1000)
|
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
|
end_ms = start_ms + 86_400_000 - 1
|
||||||
result = await execute_on_client(
|
result = await execute_on_client(
|
||||||
action="select",
|
action="select",
|
||||||
|
|||||||
@@ -226,6 +226,7 @@ async def _handle_home_request(
|
|||||||
context: dict = {
|
context: dict = {
|
||||||
"conversation_history": frame.get("conversation_history", []),
|
"conversation_history": frame.get("conversation_history", []),
|
||||||
"_debug": {"request_id": request_id, "session_id": session_id, "user_id": user_id},
|
"_debug": {"request_id": request_id, "session_id": session_id, "user_id": user_id},
|
||||||
|
"format_prefs": frame.get("format_prefs"),
|
||||||
**memory_context,
|
**memory_context,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,6 +296,7 @@ async def _handle_floating_request(
|
|||||||
context: dict = {
|
context: dict = {
|
||||||
"scope": scope,
|
"scope": scope,
|
||||||
"_debug": {"request_id": request_id, "session_id": session_id, "user_id": user_id},
|
"_debug": {"request_id": request_id, "session_id": session_id, "user_id": user_id},
|
||||||
|
"format_prefs": frame.get("format_prefs"),
|
||||||
**memory_context,
|
**memory_context,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,6 +382,7 @@ async def _handle_brief_request(
|
|||||||
|
|
||||||
context: dict = {
|
context: dict = {
|
||||||
"_debug": {"request_id": request_id, "session_id": session_id, "user_id": user_id},
|
"_debug": {"request_id": request_id, "session_id": session_id, "user_id": user_id},
|
||||||
|
"format_prefs": frame.get("format_prefs"),
|
||||||
**memory_context,
|
**memory_context,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,42 @@ def _language_instruction(context: dict[str, Any]) -> str:
|
|||||||
f"All your output text must be written in {lang}."
|
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:
|
def _proactive_hints_injection(context: dict[str, Any]) -> str:
|
||||||
"""Return a system-prompt paragraph listing proactive behavioral hints.
|
"""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 += _relational_memory_injection(context)
|
||||||
system_prompt += _proactive_hints_injection(context)
|
system_prompt += _proactive_hints_injection(context)
|
||||||
|
system_prompt += _datetime_context_injection(context)
|
||||||
system_prompt += _language_instruction(context)
|
system_prompt += _language_instruction(context)
|
||||||
response = await _run_single_agent(
|
response = await _run_single_agent(
|
||||||
user_id=user_id,
|
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 += _relational_memory_injection(context)
|
||||||
system_prompt += _proactive_hints_injection(context)
|
system_prompt += _proactive_hints_injection(context)
|
||||||
|
system_prompt += _datetime_context_injection(context)
|
||||||
system_prompt += _language_instruction(context)
|
system_prompt += _language_instruction(context)
|
||||||
response = await _run_single_agent(
|
response = await _run_single_agent(
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
@@ -984,6 +1022,7 @@ async def run_home_stream(
|
|||||||
)
|
)
|
||||||
system_prompt += _relational_memory_injection(context)
|
system_prompt += _relational_memory_injection(context)
|
||||||
system_prompt += _proactive_hints_injection(context)
|
system_prompt += _proactive_hints_injection(context)
|
||||||
|
system_prompt += _datetime_context_injection(context)
|
||||||
system_prompt += _language_instruction(context)
|
system_prompt += _language_instruction(context)
|
||||||
text_chunks: list[str] = []
|
text_chunks: list[str] = []
|
||||||
async for event in _run_single_agent_stream(
|
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 += _relational_memory_injection(context)
|
||||||
system_prompt += _proactive_hints_injection(context)
|
system_prompt += _proactive_hints_injection(context)
|
||||||
|
system_prompt += _datetime_context_injection(context)
|
||||||
system_prompt += _language_instruction(context)
|
system_prompt += _language_instruction(context)
|
||||||
sanitizer = _FloatingStreamSanitizer()
|
sanitizer = _FloatingStreamSanitizer()
|
||||||
emitted_sanitized = False
|
emitted_sanitized = False
|
||||||
|
|||||||
@@ -142,6 +142,16 @@ class WsDeviceHello(BaseModel):
|
|||||||
|
|
||||||
# ── WebSocket v3 Frame Models ─────────────────────────────────────────
|
# ── 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):
|
class WsFloatingScope(BaseModel):
|
||||||
"""Scope for a floating request — narrows the agent to a specific entity."""
|
"""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
|
type: Literal[WsFrameType.home_request] = WsFrameType.home_request
|
||||||
message: str
|
message: str
|
||||||
conversation_history: list[dict[str, Any]] = Field(default_factory=list)
|
conversation_history: list[dict[str, Any]] = Field(default_factory=list)
|
||||||
|
format_prefs: FormatPrefsModel | None = None
|
||||||
|
|
||||||
|
|
||||||
class WsFloatingRequest(BaseModel):
|
class WsFloatingRequest(BaseModel):
|
||||||
@@ -163,6 +174,7 @@ class WsFloatingRequest(BaseModel):
|
|||||||
type: Literal[WsFrameType.floating_request] = WsFrameType.floating_request
|
type: Literal[WsFrameType.floating_request] = WsFrameType.floating_request
|
||||||
message: str
|
message: str
|
||||||
scope: WsFloatingScope
|
scope: WsFloatingScope
|
||||||
|
format_prefs: FormatPrefsModel | None = None
|
||||||
|
|
||||||
|
|
||||||
class WsBriefRequest(BaseModel):
|
class WsBriefRequest(BaseModel):
|
||||||
@@ -173,6 +185,7 @@ class WsBriefRequest(BaseModel):
|
|||||||
session_id: str | None = None
|
session_id: str | None = None
|
||||||
mode: Literal["home", "project"]
|
mode: Literal["home", "project"]
|
||||||
project_id: str | None = None
|
project_id: str | None = None
|
||||||
|
format_prefs: FormatPrefsModel | None = None
|
||||||
|
|
||||||
|
|
||||||
class WsStreamStart(BaseModel):
|
class WsStreamStart(BaseModel):
|
||||||
|
|||||||
Reference in New Issue
Block a user