fix(reme): use timezone-aware datetime in memory summarization (#165)

Use user-specified timezone instead of system local time when generating
daily note filenames and timestamps in memory summarization and CLI.

Changes:
- Summarizer: accept 'timezone' param in __init__; use
  datetime.now(zoneinfo.ZoneInfo(tz)) instead of naive datetime.now()
- ReMeLight.summary_memory(): accept 'timezone' param and pass to Summarizer
- CliAgent: accept 'timezone' param in __init__; pass to Summarizer
  and use for current_time timestamp in system prompts
- Fallback to system local time if timezone is None (preserves original behavior)

Fixes timezone mismatch when system timezone differs from user's actual
location (e.g., server in UTC+8 but user in America/Chicago).
This commit is contained in:
aquamarine 2026-03-19 02:24:52 -05:00 committed by GitHub
parent 09ab707e98
commit 940a2f47a9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 21 additions and 2 deletions

View file

@ -3,6 +3,7 @@
import asyncio
from datetime import datetime
from pathlib import Path
import zoneinfo
from agentscope.agent import ReActAgent
from agentscope.message import Msg, TextBlock
@ -46,6 +47,7 @@ class CliAgent(BaseOp):
reserve_tokens: int = 36000,
keep_recent_tokens: int = 20000,
language: str = "zh",
timezone: str | None = None,
**kwargs,
):
super().__init__(**kwargs)
@ -57,6 +59,7 @@ class CliAgent(BaseOp):
self.reserve_tokens: int = reserve_tokens
self.keep_recent_tokens: int = keep_recent_tokens
self.language: str = language
self.timezone: str | None = timezone
# Initialize message history
self.messages: list[Msg] = []
@ -93,6 +96,7 @@ class CliAgent(BaseOp):
as_llm_formatter=self.as_llm_formatter,
language=self.language if self.language == "zh" else "",
console_enabled=False, # We disable the terminal printing to avoid messy outputs
timezone=self.timezone,
)
# Create summary task
@ -168,6 +172,7 @@ class CliAgent(BaseOp):
as_llm_formatter=self.as_llm_formatter,
language=self.language if self.language == "zh" else "",
console_enabled=False, # We disable the terminal printing to avoid messy outputs
timezone=self.timezone,
)
summary_content = await compactor.call(
@ -195,7 +200,8 @@ class CliAgent(BaseOp):
async def _build_messages(self, query: str) -> list[Msg]:
"""Build system prompt message."""
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S %A")
tz = zoneinfo.ZoneInfo(self.timezone) if self.timezone else None
current_time = datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S %A")
# Create system prompt
system_prompt = self.prompt_format(

View file

@ -1,6 +1,7 @@
"""Summarizer module for memory summarization operations."""
import datetime
import zoneinfo
from agentscope.agent import ReActAgent
from agentscope.message import Msg
@ -23,6 +24,7 @@ class Summarizer(BaseOp):
memory_compact_threshold: int,
toolkit: Toolkit | None = None,
console_enabled: bool = False,
timezone: str | None = None,
**kwargs,
):
super().__init__(**kwargs)
@ -31,6 +33,7 @@ class Summarizer(BaseOp):
self.memory_compact_threshold: int = memory_compact_threshold
self.toolkit: Toolkit | None = toolkit
self.console_enabled: bool = console_enabled
self.timezone: str | None = timezone
async def execute(self):
messages: list[Msg] = self.context.get("messages", [])
@ -62,7 +65,13 @@ class Summarizer(BaseOp):
user_message: str = f"<conversation>\n{history_formatted_str}\n</conversation>\n" + self.prompt_format(
"user_message",
date=datetime.datetime.now().strftime("%Y-%m-%d"),
date=(
datetime.datetime.now(
zoneinfo.ZoneInfo(self.timezone),
)
if self.timezone
else datetime.datetime.now()
).strftime("%Y-%m-%d"),
working_dir=self.working_dir,
memory_dir=self.memory_dir,
)

View file

@ -406,6 +406,7 @@ class ReMeLight(Application):
language: str = "zh",
max_input_length: float = 128 * 1024,
compact_ratio: float = 0.7,
timezone: str | None = None,
) -> str:
"""
Generate a comprehensive summary of the given messages.
@ -430,6 +431,8 @@ class ReMeLight(Application):
Defaults to 128K tokens.
compact_ratio (float): Ratio used to calculate compaction threshold.
Defaults to 0.7.
timezone (str | None): Timezone string for date formatting
(e.g., "America/Chicago"). Defaults to system local time if None.
Returns:
str: The generated summary text, or an empty string if an error occurred.
@ -455,6 +458,7 @@ class ReMeLight(Application):
as_llm_formatter=as_llm_formatter,
as_token_counter=as_token_counter,
language=language if language == "zh" else "",
timezone=timezone,
)
return await summarizer.call(messages=messages, service_context=self.service_context)