2026-02-01 10:03:47 +09:00
|
|
|
import type { OpenClawConfig } from "../../config/types.js";
|
2026-01-28 21:59:21 -05:00
|
|
|
import { resolveUserTimezone } from "../../agents/date-time.js";
|
2026-02-08 04:53:31 -08:00
|
|
|
import { formatZonedTimestamp } from "../../infra/format-time/format-datetime.ts";
|
feat(gateway): inject timestamps into agent handler messages
Messages arriving through the gateway agent method (TUI, web, spawned
subagents, sessions_send, heartbeats) now get a timestamp prefix
automatically. This gives all agent contexts date/time awareness
without modifying the system prompt (which is cached for stability).
Channel messages (Discord, Telegram, etc.) already have timestamps
via envelope formatting in a separate code path and never reach
the agent handler, so there is no double-stamping risk.
Cron jobs also inject their own 'Current time:' prefix and are
detected and skipped.
Extracted as a pure function (injectTimestamp) with 12 unit tests
covering: timezone handling, 12/24h format, midnight boundaries,
envelope detection, cron detection, and empty messages.
Integration test verifies the agent handler wires it in correctly.
Closes #3658
Refs: #1897, #1928, #2108
2026-01-28 21:31:08 -05:00
|
|
|
|
|
|
|
|
/**
|
2026-01-28 21:59:21 -05:00
|
|
|
* Cron jobs inject "Current time: ..." into their messages.
|
|
|
|
|
* Skip injection for those.
|
feat(gateway): inject timestamps into agent handler messages
Messages arriving through the gateway agent method (TUI, web, spawned
subagents, sessions_send, heartbeats) now get a timestamp prefix
automatically. This gives all agent contexts date/time awareness
without modifying the system prompt (which is cached for stability).
Channel messages (Discord, Telegram, etc.) already have timestamps
via envelope formatting in a separate code path and never reach
the agent handler, so there is no double-stamping risk.
Cron jobs also inject their own 'Current time:' prefix and are
detected and skipped.
Extracted as a pure function (injectTimestamp) with 12 unit tests
covering: timezone handling, 12/24h format, midnight boundaries,
envelope detection, cron detection, and empty messages.
Integration test verifies the agent handler wires it in correctly.
Closes #3658
Refs: #1897, #1928, #2108
2026-01-28 21:31:08 -05:00
|
|
|
*/
|
2026-01-28 21:59:21 -05:00
|
|
|
const CRON_TIME_PATTERN = /Current time: /;
|
feat(gateway): inject timestamps into agent handler messages
Messages arriving through the gateway agent method (TUI, web, spawned
subagents, sessions_send, heartbeats) now get a timestamp prefix
automatically. This gives all agent contexts date/time awareness
without modifying the system prompt (which is cached for stability).
Channel messages (Discord, Telegram, etc.) already have timestamps
via envelope formatting in a separate code path and never reach
the agent handler, so there is no double-stamping risk.
Cron jobs also inject their own 'Current time:' prefix and are
detected and skipped.
Extracted as a pure function (injectTimestamp) with 12 unit tests
covering: timezone handling, 12/24h format, midnight boundaries,
envelope detection, cron detection, and empty messages.
Integration test verifies the agent handler wires it in correctly.
Closes #3658
Refs: #1897, #1928, #2108
2026-01-28 21:31:08 -05:00
|
|
|
|
|
|
|
|
/**
|
2026-01-28 21:59:21 -05:00
|
|
|
* Matches a leading `[... YYYY-MM-DD HH:MM ...]` envelope — either from
|
|
|
|
|
* channel plugins or from a previous injection. Uses the same YYYY-MM-DD
|
|
|
|
|
* HH:MM format as {@link formatZonedTimestamp}, so detection stays in sync
|
|
|
|
|
* with the formatting.
|
feat(gateway): inject timestamps into agent handler messages
Messages arriving through the gateway agent method (TUI, web, spawned
subagents, sessions_send, heartbeats) now get a timestamp prefix
automatically. This gives all agent contexts date/time awareness
without modifying the system prompt (which is cached for stability).
Channel messages (Discord, Telegram, etc.) already have timestamps
via envelope formatting in a separate code path and never reach
the agent handler, so there is no double-stamping risk.
Cron jobs also inject their own 'Current time:' prefix and are
detected and skipped.
Extracted as a pure function (injectTimestamp) with 12 unit tests
covering: timezone handling, 12/24h format, midnight boundaries,
envelope detection, cron detection, and empty messages.
Integration test verifies the agent handler wires it in correctly.
Closes #3658
Refs: #1897, #1928, #2108
2026-01-28 21:31:08 -05:00
|
|
|
*/
|
2026-01-28 21:59:21 -05:00
|
|
|
const TIMESTAMP_ENVELOPE_PATTERN = /^\[.*\d{4}-\d{2}-\d{2} \d{2}:\d{2}/;
|
feat(gateway): inject timestamps into agent handler messages
Messages arriving through the gateway agent method (TUI, web, spawned
subagents, sessions_send, heartbeats) now get a timestamp prefix
automatically. This gives all agent contexts date/time awareness
without modifying the system prompt (which is cached for stability).
Channel messages (Discord, Telegram, etc.) already have timestamps
via envelope formatting in a separate code path and never reach
the agent handler, so there is no double-stamping risk.
Cron jobs also inject their own 'Current time:' prefix and are
detected and skipped.
Extracted as a pure function (injectTimestamp) with 12 unit tests
covering: timezone handling, 12/24h format, midnight boundaries,
envelope detection, cron detection, and empty messages.
Integration test verifies the agent handler wires it in correctly.
Closes #3658
Refs: #1897, #1928, #2108
2026-01-28 21:31:08 -05:00
|
|
|
|
|
|
|
|
export interface TimestampInjectionOptions {
|
|
|
|
|
timezone?: string;
|
|
|
|
|
now?: Date;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2026-01-28 21:59:21 -05:00
|
|
|
* Injects a compact timestamp prefix into a message if one isn't already
|
|
|
|
|
* present. Uses the same `YYYY-MM-DD HH:MM TZ` format as channel envelope
|
|
|
|
|
* timestamps ({@link formatZonedTimestamp}), keeping token cost low (~7
|
|
|
|
|
* tokens) and format consistent across all agent contexts.
|
feat(gateway): inject timestamps into agent handler messages
Messages arriving through the gateway agent method (TUI, web, spawned
subagents, sessions_send, heartbeats) now get a timestamp prefix
automatically. This gives all agent contexts date/time awareness
without modifying the system prompt (which is cached for stability).
Channel messages (Discord, Telegram, etc.) already have timestamps
via envelope formatting in a separate code path and never reach
the agent handler, so there is no double-stamping risk.
Cron jobs also inject their own 'Current time:' prefix and are
detected and skipped.
Extracted as a pure function (injectTimestamp) with 12 unit tests
covering: timezone handling, 12/24h format, midnight boundaries,
envelope detection, cron detection, and empty messages.
Integration test verifies the agent handler wires it in correctly.
Closes #3658
Refs: #1897, #1928, #2108
2026-01-28 21:31:08 -05:00
|
|
|
*
|
2026-01-28 21:59:21 -05:00
|
|
|
* Used by the gateway `agent` and `chat.send` handlers to give TUI, web,
|
|
|
|
|
* spawned subagents, `sessions_send`, and heartbeat wake events date/time
|
|
|
|
|
* awareness — without modifying the system prompt (which is cached).
|
feat(gateway): inject timestamps into agent handler messages
Messages arriving through the gateway agent method (TUI, web, spawned
subagents, sessions_send, heartbeats) now get a timestamp prefix
automatically. This gives all agent contexts date/time awareness
without modifying the system prompt (which is cached for stability).
Channel messages (Discord, Telegram, etc.) already have timestamps
via envelope formatting in a separate code path and never reach
the agent handler, so there is no double-stamping risk.
Cron jobs also inject their own 'Current time:' prefix and are
detected and skipped.
Extracted as a pure function (injectTimestamp) with 12 unit tests
covering: timezone handling, 12/24h format, midnight boundaries,
envelope detection, cron detection, and empty messages.
Integration test verifies the agent handler wires it in correctly.
Closes #3658
Refs: #1897, #1928, #2108
2026-01-28 21:31:08 -05:00
|
|
|
*
|
|
|
|
|
* Channel messages (Discord, Telegram, etc.) already have timestamps via
|
|
|
|
|
* envelope formatting and take a separate code path — they never reach
|
2026-01-28 21:59:21 -05:00
|
|
|
* these handlers, so there is no double-stamping risk. The detection
|
|
|
|
|
* pattern is a safety net for edge cases.
|
feat(gateway): inject timestamps into agent handler messages
Messages arriving through the gateway agent method (TUI, web, spawned
subagents, sessions_send, heartbeats) now get a timestamp prefix
automatically. This gives all agent contexts date/time awareness
without modifying the system prompt (which is cached for stability).
Channel messages (Discord, Telegram, etc.) already have timestamps
via envelope formatting in a separate code path and never reach
the agent handler, so there is no double-stamping risk.
Cron jobs also inject their own 'Current time:' prefix and are
detected and skipped.
Extracted as a pure function (injectTimestamp) with 12 unit tests
covering: timezone handling, 12/24h format, midnight boundaries,
envelope detection, cron detection, and empty messages.
Integration test verifies the agent handler wires it in correctly.
Closes #3658
Refs: #1897, #1928, #2108
2026-01-28 21:31:08 -05:00
|
|
|
*
|
|
|
|
|
* @see https://github.com/moltbot/moltbot/issues/3658
|
|
|
|
|
*/
|
|
|
|
|
export function injectTimestamp(message: string, opts?: TimestampInjectionOptions): string {
|
2026-01-31 09:24:27 -06:00
|
|
|
if (!message.trim()) {
|
|
|
|
|
return message;
|
|
|
|
|
}
|
feat(gateway): inject timestamps into agent handler messages
Messages arriving through the gateway agent method (TUI, web, spawned
subagents, sessions_send, heartbeats) now get a timestamp prefix
automatically. This gives all agent contexts date/time awareness
without modifying the system prompt (which is cached for stability).
Channel messages (Discord, Telegram, etc.) already have timestamps
via envelope formatting in a separate code path and never reach
the agent handler, so there is no double-stamping risk.
Cron jobs also inject their own 'Current time:' prefix and are
detected and skipped.
Extracted as a pure function (injectTimestamp) with 12 unit tests
covering: timezone handling, 12/24h format, midnight boundaries,
envelope detection, cron detection, and empty messages.
Integration test verifies the agent handler wires it in correctly.
Closes #3658
Refs: #1897, #1928, #2108
2026-01-28 21:31:08 -05:00
|
|
|
|
2026-01-28 21:59:21 -05:00
|
|
|
// Already has an envelope or injected timestamp
|
2026-01-31 09:24:27 -06:00
|
|
|
if (TIMESTAMP_ENVELOPE_PATTERN.test(message)) {
|
|
|
|
|
return message;
|
|
|
|
|
}
|
feat(gateway): inject timestamps into agent handler messages
Messages arriving through the gateway agent method (TUI, web, spawned
subagents, sessions_send, heartbeats) now get a timestamp prefix
automatically. This gives all agent contexts date/time awareness
without modifying the system prompt (which is cached for stability).
Channel messages (Discord, Telegram, etc.) already have timestamps
via envelope formatting in a separate code path and never reach
the agent handler, so there is no double-stamping risk.
Cron jobs also inject their own 'Current time:' prefix and are
detected and skipped.
Extracted as a pure function (injectTimestamp) with 12 unit tests
covering: timezone handling, 12/24h format, midnight boundaries,
envelope detection, cron detection, and empty messages.
Integration test verifies the agent handler wires it in correctly.
Closes #3658
Refs: #1897, #1928, #2108
2026-01-28 21:31:08 -05:00
|
|
|
|
|
|
|
|
// Already has a cron-injected timestamp
|
2026-01-31 09:24:27 -06:00
|
|
|
if (CRON_TIME_PATTERN.test(message)) {
|
|
|
|
|
return message;
|
|
|
|
|
}
|
feat(gateway): inject timestamps into agent handler messages
Messages arriving through the gateway agent method (TUI, web, spawned
subagents, sessions_send, heartbeats) now get a timestamp prefix
automatically. This gives all agent contexts date/time awareness
without modifying the system prompt (which is cached for stability).
Channel messages (Discord, Telegram, etc.) already have timestamps
via envelope formatting in a separate code path and never reach
the agent handler, so there is no double-stamping risk.
Cron jobs also inject their own 'Current time:' prefix and are
detected and skipped.
Extracted as a pure function (injectTimestamp) with 12 unit tests
covering: timezone handling, 12/24h format, midnight boundaries,
envelope detection, cron detection, and empty messages.
Integration test verifies the agent handler wires it in correctly.
Closes #3658
Refs: #1897, #1928, #2108
2026-01-28 21:31:08 -05:00
|
|
|
|
|
|
|
|
const now = opts?.now ?? new Date();
|
|
|
|
|
const timezone = opts?.timezone ?? "UTC";
|
|
|
|
|
|
2026-02-08 04:53:31 -08:00
|
|
|
const formatted = formatZonedTimestamp(now, { timeZone: timezone });
|
2026-01-31 09:24:27 -06:00
|
|
|
if (!formatted) {
|
|
|
|
|
return message;
|
|
|
|
|
}
|
feat(gateway): inject timestamps into agent handler messages
Messages arriving through the gateway agent method (TUI, web, spawned
subagents, sessions_send, heartbeats) now get a timestamp prefix
automatically. This gives all agent contexts date/time awareness
without modifying the system prompt (which is cached for stability).
Channel messages (Discord, Telegram, etc.) already have timestamps
via envelope formatting in a separate code path and never reach
the agent handler, so there is no double-stamping risk.
Cron jobs also inject their own 'Current time:' prefix and are
detected and skipped.
Extracted as a pure function (injectTimestamp) with 12 unit tests
covering: timezone handling, 12/24h format, midnight boundaries,
envelope detection, cron detection, and empty messages.
Integration test verifies the agent handler wires it in correctly.
Closes #3658
Refs: #1897, #1928, #2108
2026-01-28 21:31:08 -05:00
|
|
|
|
2026-01-28 22:40:48 -05:00
|
|
|
// 3-letter DOW: small models (8B) can't reliably derive day-of-week from
|
|
|
|
|
// a date, and may treat a bare "Wed" as a typo. Costs ~1 token.
|
2026-01-28 22:07:26 -05:00
|
|
|
const dow = new Intl.DateTimeFormat("en-US", { timeZone: timezone, weekday: "short" }).format(
|
|
|
|
|
now,
|
|
|
|
|
);
|
|
|
|
|
|
2026-01-28 22:40:48 -05:00
|
|
|
return `[${dow} ${formatted}] ${message}`;
|
feat(gateway): inject timestamps into agent handler messages
Messages arriving through the gateway agent method (TUI, web, spawned
subagents, sessions_send, heartbeats) now get a timestamp prefix
automatically. This gives all agent contexts date/time awareness
without modifying the system prompt (which is cached for stability).
Channel messages (Discord, Telegram, etc.) already have timestamps
via envelope formatting in a separate code path and never reach
the agent handler, so there is no double-stamping risk.
Cron jobs also inject their own 'Current time:' prefix and are
detected and skipped.
Extracted as a pure function (injectTimestamp) with 12 unit tests
covering: timezone handling, 12/24h format, midnight boundaries,
envelope detection, cron detection, and empty messages.
Integration test verifies the agent handler wires it in correctly.
Closes #3658
Refs: #1897, #1928, #2108
2026-01-28 21:31:08 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2026-01-31 09:24:27 -06:00
|
|
|
* Build TimestampInjectionOptions from an OpenClawConfig.
|
feat(gateway): inject timestamps into agent handler messages
Messages arriving through the gateway agent method (TUI, web, spawned
subagents, sessions_send, heartbeats) now get a timestamp prefix
automatically. This gives all agent contexts date/time awareness
without modifying the system prompt (which is cached for stability).
Channel messages (Discord, Telegram, etc.) already have timestamps
via envelope formatting in a separate code path and never reach
the agent handler, so there is no double-stamping risk.
Cron jobs also inject their own 'Current time:' prefix and are
detected and skipped.
Extracted as a pure function (injectTimestamp) with 12 unit tests
covering: timezone handling, 12/24h format, midnight boundaries,
envelope detection, cron detection, and empty messages.
Integration test verifies the agent handler wires it in correctly.
Closes #3658
Refs: #1897, #1928, #2108
2026-01-28 21:31:08 -05:00
|
|
|
*/
|
2026-01-31 09:24:27 -06:00
|
|
|
export function timestampOptsFromConfig(cfg: OpenClawConfig): TimestampInjectionOptions {
|
feat(gateway): inject timestamps into agent handler messages
Messages arriving through the gateway agent method (TUI, web, spawned
subagents, sessions_send, heartbeats) now get a timestamp prefix
automatically. This gives all agent contexts date/time awareness
without modifying the system prompt (which is cached for stability).
Channel messages (Discord, Telegram, etc.) already have timestamps
via envelope formatting in a separate code path and never reach
the agent handler, so there is no double-stamping risk.
Cron jobs also inject their own 'Current time:' prefix and are
detected and skipped.
Extracted as a pure function (injectTimestamp) with 12 unit tests
covering: timezone handling, 12/24h format, midnight boundaries,
envelope detection, cron detection, and empty messages.
Integration test verifies the agent handler wires it in correctly.
Closes #3658
Refs: #1897, #1928, #2108
2026-01-28 21:31:08 -05:00
|
|
|
return {
|
|
|
|
|
timezone: resolveUserTimezone(cfg.agents?.defaults?.userTimezone),
|
|
|
|
|
};
|
|
|
|
|
}
|