feat(timezone): make all user/LLM-facing timestamps timezone-configurable (#129)

Add top-level `timezone` config option (default: "system") supporting
IANA names and UTC offset strings (ECMA-402 2024).

- Introduce unified `src/utils/time.ts` module with formatForLLM,
  formatLocalDate, formatLocalDateTime, startOfLocalDay, nowInstantISO
- Converge 4 scattered time helpers into the single module
- L1 extraction / auto-recall / scene-extraction / persona-generation
  prompts now emit ISO 8601 with explicit UTC offset
- Add timezone declaration to LLM system prompts
- Local-day shard boundaries and cleaner cutoff follow configured tz
- Storage instants (SQLite/TCVDB) remain UTC — no data migration needed
- 38 unit tests covering IANA, offset, DST, half-hour zones, fallback
This commit is contained in:
Ruida Xu
2026-06-04 11:44:01 +08:00
committed by GitHub
parent c6ed755835
commit 32ba4d303d
15 changed files with 702 additions and 48 deletions
+10
View File
@@ -269,6 +269,15 @@ export interface OffloadConfig {
/** Fully resolved plugin configuration (v3). */
export interface MemoryTdaiConfig {
/**
* Timezone for user/LLM-facing timestamps and local-day boundaries.
* - "system" (default): follow process system timezone
* - IANA name: "Asia/Shanghai", "Europe/Berlin", "UTC"
* - UTC offset string: "+08:00", "-05:30" (ECMA-402 2024)
*
* Storage instants (SQLite/TCVDB) are always UTC regardless of this setting.
*/
timezone: string;
capture: CaptureConfig;
extraction: ExtractionConfig;
persona: PersonaConfig;
@@ -468,6 +477,7 @@ export function parseConfig(raw: Record<string, unknown> | undefined): MemoryTda
};
return {
timezone: str(c, "timezone") ?? "system",
capture: {
enabled: bool(captureGroup, "enabled") ?? true,
excludeAgents: strArray(captureGroup, "excludeAgents") ?? [],