mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-19 11:58:38 +00:00
fix: default envelope timestamps to local
This commit is contained in:
@@ -13,6 +13,9 @@ Docs: https://docs.clawd.bot
|
|||||||
- Signal: add typing indicators and DM read receipts via signal-cli.
|
- Signal: add typing indicators and DM read receipts via signal-cli.
|
||||||
- MSTeams: add file uploads, adaptive cards, and attachment handling improvements. (#1410) Thanks @Evizero.
|
- MSTeams: add file uploads, adaptive cards, and attachment handling improvements. (#1410) Thanks @Evizero.
|
||||||
|
|
||||||
|
### Breaking
|
||||||
|
- **BREAKING:** Envelope timestamps now default to host-local time (was UTC) so agents don’t have to constantly convert.
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
- Config: avoid stack traces for invalid configs and log the config path.
|
- Config: avoid stack traces for invalid configs and log the config path.
|
||||||
- Doctor: warn when gateway.mode is unset with configure/config guidance.
|
- Doctor: warn when gateway.mode is unset with configure/config guidance.
|
||||||
|
|||||||
@@ -9,15 +9,15 @@ read_when:
|
|||||||
|
|
||||||
Clawdbot standardizes timestamps so the model sees a **single reference time**.
|
Clawdbot standardizes timestamps so the model sees a **single reference time**.
|
||||||
|
|
||||||
## Message envelopes (UTC by default)
|
## Message envelopes (local by default)
|
||||||
|
|
||||||
Inbound messages are wrapped in an envelope like:
|
Inbound messages are wrapped in an envelope like:
|
||||||
|
|
||||||
```
|
```
|
||||||
[Provider ... 2026-01-05T21:26Z] message text
|
[Provider ... 2026-01-05 16:26 PST] message text
|
||||||
```
|
```
|
||||||
|
|
||||||
The timestamp in the envelope is **UTC by default**, with minutes precision.
|
The timestamp in the envelope is **host-local by default**, with minutes precision.
|
||||||
|
|
||||||
You can override this with:
|
You can override this with:
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ You can override this with:
|
|||||||
{
|
{
|
||||||
agents: {
|
agents: {
|
||||||
defaults: {
|
defaults: {
|
||||||
envelopeTimezone: "user", // "utc" | "local" | "user" | IANA timezone
|
envelopeTimezone: "local", // "utc" | "local" | "user" | IANA timezone
|
||||||
envelopeTimestamp: "on", // "on" | "off"
|
envelopeTimestamp: "on", // "on" | "off"
|
||||||
envelopeElapsed: "on" // "on" | "off"
|
envelopeElapsed: "on" // "on" | "off"
|
||||||
}
|
}
|
||||||
@@ -33,6 +33,7 @@ You can override this with:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- `envelopeTimezone: "utc"` uses UTC.
|
||||||
- `envelopeTimezone: "user"` uses `agents.defaults.userTimezone` (falls back to host timezone).
|
- `envelopeTimezone: "user"` uses `agents.defaults.userTimezone` (falls back to host timezone).
|
||||||
- Use an explicit IANA timezone (e.g., `"Europe/Vienna"`) for a fixed offset.
|
- Use an explicit IANA timezone (e.g., `"Europe/Vienna"`) for a fixed offset.
|
||||||
- `envelopeTimestamp: "off"` removes absolute timestamps from envelope headers.
|
- `envelopeTimestamp: "off"` removes absolute timestamps from envelope headers.
|
||||||
@@ -40,10 +41,10 @@ You can override this with:
|
|||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
**UTC (default):**
|
**Local (default):**
|
||||||
|
|
||||||
```
|
```
|
||||||
[Signal Alice +1555 2026-01-18T05:19Z] hello
|
[Signal Alice +1555 2026-01-18 00:19 PST] hello
|
||||||
```
|
```
|
||||||
|
|
||||||
**Fixed timezone:**
|
**Fixed timezone:**
|
||||||
|
|||||||
@@ -7,18 +7,18 @@ read_when:
|
|||||||
|
|
||||||
# Date & Time
|
# Date & Time
|
||||||
|
|
||||||
Clawdbot defaults to **UTC for transport timestamps** and **user-local time only in the system prompt**.
|
Clawdbot defaults to **host-local time for transport timestamps** and **user-local time only in the system prompt**.
|
||||||
Provider timestamps are preserved so tools keep their native semantics.
|
Provider timestamps are preserved so tools keep their native semantics.
|
||||||
|
|
||||||
## Message envelopes (UTC by default)
|
## Message envelopes (local by default)
|
||||||
|
|
||||||
Inbound messages are wrapped with a UTC timestamp (minute precision):
|
Inbound messages are wrapped with a timestamp (minute precision):
|
||||||
|
|
||||||
```
|
```
|
||||||
[Provider ... 2026-01-05T21:26Z] message text
|
[Provider ... 2026-01-05 16:26 PST] message text
|
||||||
```
|
```
|
||||||
|
|
||||||
This envelope timestamp is **UTC by default**, regardless of the host timezone.
|
This envelope timestamp is **host-local by default**, regardless of the provider timezone.
|
||||||
|
|
||||||
You can override this behavior:
|
You can override this behavior:
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ You can override this behavior:
|
|||||||
{
|
{
|
||||||
agents: {
|
agents: {
|
||||||
defaults: {
|
defaults: {
|
||||||
envelopeTimezone: "utc", // "utc" | "local" | "user" | IANA timezone
|
envelopeTimezone: "local", // "utc" | "local" | "user" | IANA timezone
|
||||||
envelopeTimestamp: "on", // "on" | "off"
|
envelopeTimestamp: "on", // "on" | "off"
|
||||||
envelopeElapsed: "on" // "on" | "off"
|
envelopeElapsed: "on" // "on" | "off"
|
||||||
}
|
}
|
||||||
@@ -34,6 +34,7 @@ You can override this behavior:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- `envelopeTimezone: "utc"` uses UTC.
|
||||||
- `envelopeTimezone: "local"` uses the host timezone.
|
- `envelopeTimezone: "local"` uses the host timezone.
|
||||||
- `envelopeTimezone: "user"` uses `agents.defaults.userTimezone` (falls back to host timezone).
|
- `envelopeTimezone: "user"` uses `agents.defaults.userTimezone` (falls back to host timezone).
|
||||||
- Use an explicit IANA timezone (e.g., `"America/Chicago"`) for a fixed zone.
|
- Use an explicit IANA timezone (e.g., `"America/Chicago"`) for a fixed zone.
|
||||||
@@ -42,10 +43,10 @@ You can override this behavior:
|
|||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
**UTC (default):**
|
**Local (default):**
|
||||||
|
|
||||||
```
|
```
|
||||||
[WhatsApp +1555 2026-01-18T05:19Z] hello
|
[WhatsApp +1555 2026-01-18 00:19 PST] hello
|
||||||
```
|
```
|
||||||
|
|
||||||
**User timezone:**
|
**User timezone:**
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ describe("formatAgentEnvelope", () => {
|
|||||||
host: "mac-mini",
|
host: "mac-mini",
|
||||||
ip: "10.0.0.5",
|
ip: "10.0.0.5",
|
||||||
timestamp: ts,
|
timestamp: ts,
|
||||||
|
envelope: { timezone: "utc" },
|
||||||
body: "hello",
|
body: "hello",
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ describe("formatAgentEnvelope", () => {
|
|||||||
expect(body).toBe("[WebChat user1 mac-mini 10.0.0.5 2025-01-02T03:04Z] hello");
|
expect(body).toBe("[WebChat user1 mac-mini 10.0.0.5 2025-01-02T03:04Z] hello");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("formats timestamps in UTC regardless of local timezone", () => {
|
it("formats timestamps in local timezone by default", () => {
|
||||||
const originalTz = process.env.TZ;
|
const originalTz = process.env.TZ;
|
||||||
process.env.TZ = "America/Los_Angeles";
|
process.env.TZ = "America/Los_Angeles";
|
||||||
|
|
||||||
@@ -39,10 +40,10 @@ describe("formatAgentEnvelope", () => {
|
|||||||
|
|
||||||
process.env.TZ = originalTz;
|
process.env.TZ = originalTz;
|
||||||
|
|
||||||
expect(body).toBe("[WebChat 2025-01-02T03:04Z] hello");
|
expect(body).toMatch(/\[WebChat 2025-01-01 19:04 [^\]]+\] hello/);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("formats timestamps in local timezone when configured", () => {
|
it("formats timestamps in UTC when configured", () => {
|
||||||
const originalTz = process.env.TZ;
|
const originalTz = process.env.TZ;
|
||||||
process.env.TZ = "America/Los_Angeles";
|
process.env.TZ = "America/Los_Angeles";
|
||||||
|
|
||||||
@@ -50,13 +51,13 @@ describe("formatAgentEnvelope", () => {
|
|||||||
const body = formatAgentEnvelope({
|
const body = formatAgentEnvelope({
|
||||||
channel: "WebChat",
|
channel: "WebChat",
|
||||||
timestamp: ts,
|
timestamp: ts,
|
||||||
envelope: { timezone: "local" },
|
envelope: { timezone: "utc" },
|
||||||
body: "hello",
|
body: "hello",
|
||||||
});
|
});
|
||||||
|
|
||||||
process.env.TZ = originalTz;
|
process.env.TZ = originalTz;
|
||||||
|
|
||||||
expect(body).toMatch(/\[WebChat 2025-01-01 19:04 [^\]]+\] hello/);
|
expect(body).toBe("[WebChat 2025-01-02T03:04Z] hello");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("formats timestamps in user timezone when configured", () => {
|
it("formats timestamps in user timezone when configured", () => {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export type AgentEnvelopeParams = {
|
|||||||
|
|
||||||
export type EnvelopeFormatOptions = {
|
export type EnvelopeFormatOptions = {
|
||||||
/**
|
/**
|
||||||
* "utc" (default), "local", "user", or an explicit IANA timezone string.
|
* "local" (default), "utc", "user", or an explicit IANA timezone string.
|
||||||
*/
|
*/
|
||||||
timezone?: string;
|
timezone?: string;
|
||||||
/**
|
/**
|
||||||
@@ -59,7 +59,7 @@ function normalizeEnvelopeOptions(options?: EnvelopeFormatOptions): NormalizedEn
|
|||||||
const includeTimestamp = options?.includeTimestamp !== false;
|
const includeTimestamp = options?.includeTimestamp !== false;
|
||||||
const includeElapsed = options?.includeElapsed !== false;
|
const includeElapsed = options?.includeElapsed !== false;
|
||||||
return {
|
return {
|
||||||
timezone: options?.timezone?.trim() || "utc",
|
timezone: options?.timezone?.trim() || "local",
|
||||||
includeTimestamp,
|
includeTimestamp,
|
||||||
includeElapsed,
|
includeElapsed,
|
||||||
userTimezone: options?.userTimezone,
|
userTimezone: options?.userTimezone,
|
||||||
@@ -77,7 +77,7 @@ function resolveExplicitTimezone(value: string): string | undefined {
|
|||||||
|
|
||||||
function resolveEnvelopeTimezone(options: NormalizedEnvelopeOptions): ResolvedEnvelopeTimezone {
|
function resolveEnvelopeTimezone(options: NormalizedEnvelopeOptions): ResolvedEnvelopeTimezone {
|
||||||
const trimmed = options.timezone?.trim();
|
const trimmed = options.timezone?.trim();
|
||||||
if (!trimmed) return { mode: "utc" };
|
if (!trimmed) return { mode: "local" };
|
||||||
const lowered = trimmed.toLowerCase();
|
const lowered = trimmed.toLowerCase();
|
||||||
if (lowered === "utc" || lowered === "gmt") return { mode: "utc" };
|
if (lowered === "utc" || lowered === "gmt") return { mode: "utc" };
|
||||||
if (lowered === "local" || lowered === "host") return { mode: "local" };
|
if (lowered === "local" || lowered === "host") return { mode: "local" };
|
||||||
|
|||||||
Reference in New Issue
Block a user